On Type Safety

This afternoon I've been reading "Rubyisms in Rails" by Jacob Harris. It's a little PDF download from Addison Wesley about how various aspects of the Ruby language enabled Rails to come into being, and I've been enjoying it quite a bit. I had to stop and laugh when I saw the following quote though:

Because it is not compiled and has no static types, Ruby might seem to be more dangerous to develop in; but in some sense, it can actually be safer to program in: Because developers have no illusions that type checking is a serious defense against bugs, they will not confuse compilation with correctness.

I'm going to go out on a limb here and say that for the 90% of developers that do a bad job of testing all around, this is not going to be the case.

Also, he makes the statement:

Simple to use and well suited for their purpose, symbols are one of the unique features of Ruby.

I'll just assume that he meant to say, "Simple to use and well suited for their purpose, symbols are one of the great features of Ruby that was taken directly from Smalltalk" and his editor just took it out after he turned in his manuscript.

Overall though, it's a good quick read that does a great job of showing how Ruby makes a lot of the magic in Rails possible. Well worth the bargain price of $9.99.

Quote of the Moment

Cynos says...

I believe that the Bush government is deliberately with-holding YARV, in order to increase profits for his oil drilling buddies.

In response to Toby's excellent post on the shortcomings of the Ruby runtime.

Running Ruby in the browser via script type=”text/ruby”

I played around with getting Ruby to work in the browser while watching some cheesy TV this weekend. I was able to get things slightly working, and put this work in progress up on Google Code here. That link sends you to a page that will evaluate Ruby for you, both from a script tag, and from your own input. If you take a look at the top of the file, you will see: <script type="text/ruby"> #class Foo; def initialize; @foo = 'whee'; end; end; f = Foo.new; f Time.now </script> This script is found by the Ruby in the browser system, and is run through JRuby via a little applet. The page takes the output at the end and throws it into the container HTML on the right. You can also edit the text area at the bottom left and run your own Ruby code, and the output will be placed on the right too. Now, this is just the first baby step to get to something feature full like: <script type="text/ruby"> document.ready do |dom| dom["table tr"] <<"<td>test</td>" end </script> Just being able to run some Ruby doesn't mean much. We need to give it rich support for the browser to be able to interact with the DOM and Ajax libraries to do cool things, using the power of Ruby. So, there are a lot of TODOs here: The applet is a download of JRuby complete, which is huge, and isn't all needed. I need to work with the JRuby folk to produce a slimmed down applet version. Come up with a solution that allows you to puts data out (maybe put that data in a div somewhere), and more importantly, talk to the DOM directly from Ruby. Since the applet can contain Ruby files themselves, we can create a Ruby module that lets you do DOM stuff, that becomes JavaScript which will be eval'd to run in the browser. Or, we just give direct access. I am still playing with what makes sense there Only tested in Firefox. There are some known issues in Safari. I am lazily using an applet tag instead of the magic object/embed stuff that would make this work in other places Any direction make sense to you?

Erm, no, not really…

David says, "Rather than just sit around idle waiting for some vendor to fix your problems, you get the unique chance of being a steward of your own destiny," in reaction to Alex (of Twitter) saying Ruby is slow and Rails has no way to talk to several databases. A particular reaction to David's statement is where it went from yawn to what!?

Robert asserted that "when you are trying to build a business you don't have the luxury of digging through a ton of source code and then try to figure out the where the problems are and make changes." I disagree. You don't have the luxury of doing so, you have the requirement to do so. To put it simply, if you rely on a particular piece of software, and you need something changed, then you need it to be changed, and that is that. It is up to you.

Now, just because it is up to you doesn't mean you need to go implement the fix. Heck, you probably cannot even do it yourself unless the library is both open source and openly developed. If development is closed, your "option" is generally to throw money at the people who wrote the bug to make said bug go away.

If on the other hand you do have the option of fixing it yourself, you still rarely have to. An awful lot of the time merely pointing out the problem to folks already involved with the project will lead to it getting resolved. If just pointing it out won't get it fixed fast enough for you, it is downright shocking how many people will let you pay them to write software, so you can just pay someone to do it. If you don't have the funds or access to the information you need, you can play weird PR games to "force" them to do it (this actually works for security related stuff, frequently). If all else fails, you just fix the damned thing. That is about it: 1) ask nicely, 2) ask nicely with dollars on top, 3) threaten or bluster, 4) get sued by Nike, er, I mean, just do it.

The fact of the matter is that you need something changed in a library you use. You use this library, presumably, because it saves you a bunch of work. So you have to do a little work to still save you a bunch more work. (You might, alternately, decide that the amount of work you have to do to fix it is greater than the amount you saved, in which case you accept you made a bad call, and go do the right thing.)

Now, a key to understanding this is to realize that the people who wrote this library that is saving you a a bunch of work did it to save themselves some work. Frequently others chipped in as well. Shockingly, over time, you wind up with something like this, for example,

brianm@golem:~$ nc -v thebull.macsimumweb.com 80
DNS fwd/rev mismatch: thebull.macsimumweb.com != 209-59-185-60.webserversystems.com
thebull.macsimumweb.com [209.59.185.60] 80 (http) open
HEAD / HTTP/1.1
Host: thebull.macsimumweb.com
Connection: close

HTTP/1.1 200 OK
Date: Sun, 15 Apr 2007 05:56:30 GMT
Server: Apache/1.3.37 (Unix) mod_gzip/1.3.26.1a mod_fastcgi/2.4.2 \
        mod_auth_passthrough/1.8 mod_log_bytes/1.2 mod_bwlimited/1.4 \
        FrontPage/5.0.2.2635.SR1.2 mod_ssl/2.8.28 OpenSSL/0.9.7a PHP-CGI/0.1b
X-Powered-By: PHP/4.4.4
Connection: close
Content-Type: text/html

brianm@golem:~$ 

where a lot of folks contributed to apache, mod_gzip, mod_auth_passthrough, mod_log_bytes, mod_bwlimited, mod_ssl, OpenSSL, and PHP, so that the combined efforts have enabled a blog. Almost all of them said "oh shit, I need [foo], and [bar] doesn't do it" so went and did it. For the economics of it, go read Yochai Benkler. The gist is "you get out more than you put in."

But, you say, "Gee, I would love to write acts_as_infinitely_scalable but that pesky DHH guy won't let me change things in Rails, only the 'core team' get to do that." First off, that ain't true, they accept patches and have a good record of applying them. Second off, damned straight it is easier for them to do it -- they earned that trust. (Actually, acts_as_infinitely_scalable would probably be declined in favor of making it a plugin.)

They earned that trust for a number of reasons, but I will bet you pennies to bricks of gold that the majority got there because they relied on the project and needed more control over it. Maybe they rely on it because they are consultants who use it as advertising, possibly they need control over it in order to build up their personal ego, not infrequently they just needed increased responsibility in order to become better programmers, but most likely (I am not going to go find the citations, this is a blog not a journal) they were building products which relied on it. I doubt a single one thought about it in terms of "I need more control over [baz]," but in the end, that is what it was.

If you rely on [something], and you see it needs [something else], you do a quick calculation in your head to decide if the value of [something] is greater than the cost of [something else] and either do [something else] for [something] or ditch [something] in favor of [yet another thing] that already does [something else].

Figuring out the value and/or cost of [something], [something else], and [yet another thing] can be a pain sometimes, but that is why we get paid the big bucks :-)

script type=”my dsl” and script type=”ruby”

John Resig gave an enjoyable presentation on Javascript libraries. This wasn't a talk about choosing library A over library B. It was meta. It was about what libraries give you, and why they are here. John also showed his text/jquery DSL that is up at jquery2 (a bad name that will not probably be jquery2). We are seeing more and more of this. People are following the pattern of sneaking in their own script by putting in their own mime type and then using DOM scripting to go back and do the right thing. I am hopeful that we will see a <script type="text/ruby"> soon: <script type="text/ruby"> document.ready do |dom| dom["table tr"] <<"<td>test" end </script> Yummy. Then Try Ruby would literally be... try ruby in the browser.

Blogger supports enclosures via the GData API

I am producing a new podcast and since I was using Blogger for the podcast blog, I really wanted to be able to throw enclosures right into the feed. I had thought that Blogger didn't support enclosures, but I found that this wasn't the case. Although there isn't an area in the UI to upload files to a blog post, the GData Blogger Data API does allow you to attach an enclosure to an entry. Since the GData API works with Atom feeds, you will need to attach a correct link tag (as opposed to an <enclosure> tag from RSS) to the blog entry that you want to attach the podcast. E.g. a simple enclosure can be added as <link rel="enclosure" type="audio/mpeg" title="MP3" href=" http://foo.com/episode2.mp3 " length="19283" /> You can also add other types such as BitTorrent. To implement adding an enclosure I created a ruby script to do the work called addenclosure. This script takes a bunch of arguments: Blog ID: If you don't know your blog id, simply go to your feed at http://yourblog.blogspot.com/ /feeds/posts/default and look for the id field. It should look something like tag:blogger.com,1999:blog-4808741160899251111 . The numbers are the id that you need to plug in (4808741160899251111) Entry ID: To find this id, you can either look in the same feed and hunt for the correct entry: <entry><id>tag:blogger.com ,1999:blog-4808741160899251111.post-5004114743910071111</id>... and the numbers after the 'post-' are for the entry (5004114743910071111). You could also view the entry itself and look for the comment feed ( http://yourblog.blogspot.com/feeds/5004114743910071111/comments/default ) or various post links, that have the post id. Enclosure URL: You need to tell the script the location (URL) of the podcast itself ( e.g. http://foo.com/episode2.mp3) Enclosure Length: How big is that file? Let me know. I fully admit that it is a little ugly to have to scrounge for the various IDs, but once you run this script you can visit the feed to see a brand new enclosure link. Throw this into a podcatcher such as iTunes and Bob's your Uncle. How the script works The script itself uses my, alpha quality, GData Ruby library. The library was first factored out of gspreadsheet and consists of: GData::Base: The base library knows how to talk GData, including being able to authenticate to Google and use X-HTTP-Method-Override for HTTP methods such as PUT. It has the low level GET, PUT, POST API that other service specific libraries will build on GData::Blogger: The Blogger code knows how to speak to blogger and get and modify feeds and entries. It includes high level methods such as add_enclosure(..) GData::Spreadsheet: Likewise, the spreadsheet module has high level methods such as add_to_cell and evaluate_cell Along with the library, scripts are also packaged to show the library usage: addenclosure: what we have been talking about bloggerfeed: view the entire feed gspreadsheet: run formula removeenclosure: nuke an enclosure from an entry In the future I want to work with more GData folk to have a fully fleshed out API for Ruby-folk to talk to any GData service. A couple of people have already contacted me asking to add features ( e.g. high level support for the new Picassa APIs).