Wednesday, July 9, 2008

Announcing rubyjs_on_rails: ARAX sans silverlight

So maybe you're like me: sure javascript is nice and all but you really like ruby better. And as we move toward richer web apps, there are times it sure would be nice to write some of the client side code in ruby. Along comes M$ with their sexy silverlight DLR magic to make it happen. But you're suspicious: it requires a browser plugin, and can you really trust that it will be there on all the platforms you want to support. Sure, maybe M$ has learned how to play nice and it will be different this time. Maybe.

Well, you can quit holding your breath and exhale, girls and boys. You can write ruby code that runs in the browser right now. Today. No plugin or nuthin. So here's how. First, you'll need my forked version of the rubyjs ruby to javascript compiler. It's a little like GWT for you Java folk. Get it here. Sorry, until githubs gem building process decides to show me some love you'll need to download and install it locally with:

gem install --local rubyjs-0.8.1.gem

Next, you take standard rails app and install my superfantastic* rubyjs_on_rails plugin like so:

script/plugin install git://github.com/superchris/rubyjs_on_rails.git

So what did you get? Well, basically, one measly helper method. Sad, huh. Hey! Don't judge me! Cool your jets and let's see what it does already. First make a rails controller with a single action. Any old action will do, but let's imagine it's called hello. Go find hello.html.erb and put a single button button that doesn't do anything in it like so:

<input type="button" id="button" value="Say Hello">

Now let's write some ruby code to respond to the button click. Make a file called hello.rb in the same directory as your view and put this in it:

require 'dom_element'

class Hello
def self.main
button = DOMElement.find("button")
button.observe("click") { puts "Hello from rubyjs!"}
end
end

DOMElement is a class provided by the rubyjs gem that makes it easy to, surprise surprise, work with dom elements. In our case we just use it to grab hold of our button and observe the click event with a block of ruby code. Kind of cool I think.

But how to get this code into the brower? You remember earlier when I said all this plugin gives you is one measly helper method and you were all "Meh. I am sooo not impressed." Well now let's see it in action. Add this to your view right below the the button:

<%= rubyjs "Hello", "main" %>

Now hit this action in your browser. Click the button and you'll see your ruby block fire. The rubyjs helper method goes and finds hello.rb, compiles into javascript, and outputs a script tag to serve it up. The arguments to it are the class name and and a class method to invoke. It needs to be a class method; As this is the entry point to the code there is no instance yet to invoke methods on.

So that's it. Ruby running in the browser. You're welcome.

*Your superfasticalness may vary. No actual superfantasticness is either expressed nor implied by this blog post

4 comments:

Unknown said...

what about making it unobtrusive? also it would be nice to have rubyjs files automatically included in the view if the name is the same.

BTW interesting project!

Anonymous said...

What advantage does this offer over RJS?

MysteryCoder said...

@Cesidio interesting idea. I was thinking it was unobtrusive in that it altered behavior without touching the html. But yeah, I could just autoinclude files but I would have to assume a "main" method to invoke or something.

@Eric rubyjs is kind of like RJS on super mega steroids. While RJS gives you a few methods for emitting javascript, rubyjs takes normal ruby code (with a few caveats) and compiles it into javascript. This gives you quite a few more interesting possibilities.

Unknown said...

So awesome.

Is it possible to make use of frameworks like ExtJS from RubyJS? If so, how would you do it cleanly?