A Walkthrough of Ruby In The Web Browser using IronRuby and Silverlight
With Microsoft's IronRuby and Silverlight, Ruby can become a first-class citizen in the browser on Windows, Linux and OS X.. think <script type="text/ruby">
- yes, it's possible! This walkthrough will get you started with using Ruby in the browser for HTML and vector-graphics-based applications. IronRuby enables Web developers to use Ruby to write client-side browser applications and even reuse code between the server and the client.
Background
IronRuby is a Ruby 1.8.6-compatible implementation, with ever-increasing support for 1.9 features that runs on Microsoft's Common Language Infrastructure. The CLI blesses IronRuby with some powerful features like an efficient just-in-time compiler and sophisticated garbage collector. However, certain runtime-specific Ruby features are not supported on IronRuby, like continuations which interact with the runtime, certain performance-bogging parts of ObjectSpace, and the native Ruby C API. To support native-code interop we are planning on supporting FFI in the future (though today you can use the Win32API for Win32 calls, and the platform invoke APIs for the rest).
IronRuby runs on the .NET framework (2.0 SP1+) and Mono(2.0+), so IronRuby runs on a ton of platforms, including Mac OS and Linux. IronRuby also runs in the browser on Silverlight and Moonlight, a fairly-complete-but-tiny runtime which allows you to build "rich internet applications" ... basically anything doing vector-graphics, webcam, audio, etc, in the browser.
Getting Started
Note: All code shown in this article can be found on GitHub.
To develop browser applications with IronRuby, you just need a Web server, text-editor, Web browser, and Silverlight installed for your browser to use:
1. Download and Install Silverlight for Mac or Windows
You'll notice these installers are larger than advertised (7MB Windows, 13MB Mac): these are the "developer" versions since they contain error-message strings rather than just error codes, which is all the "consumer" versions have.
2. Set up any Web server, text-editor, and Web browser
I'll be using the latest version of Firefox for the Web browser, the Apache Web server (which is part of Mac OS), and TextMate as the text-editor; on Windows you can use IIS (or any Web server of your choice) and any text-editor of your choice (notepad.exe is already installed, but I'd suggest E-TextEditor, InType, or even gVim for the more courageous). Silverlight officially supports IE, Firefox on Windows, and Firefox and Safari on Mac OS, but Opera and Google Chrome on both operating systems are known to work. See the system requirements page for more details.
3. Write Ruby in HTML pages
Here's a simple "Hello, World"-style Ruby application in the browser:
Open the text-editor, place this code into it, and save the file to a convenient location where your Web server can access it; I'm saving mine to ~/Sites/ruby.html
, since that will let me access it from http://localhost/~<username>/ruby.html
(IIS users will have to put the file under C:inetpubwwwroot
, which will let you access it from http://localhost/ruby.html
) When you visit the site in a Web browser, you will see "Ruby says hello!":
Note: if you just see "Loading ..." for a very long time ... did you already install Silverlight? There is no install detection
in these examples. If you're on a slow connection, make sure files aren't still being downloaded (see below). And this will not run direct from the file system due to Silverlight's security sandbox, so make sure you access it through a Web server.
Behind the scenes
That's it! It's very simple to get started with IronRuby in Silverlight, especially versus using ActionScript in Flash, or even the other languages like C# or VB.NET in Silverlight. Let me briefly explain what is going on behind the scenes to make IronRuby work so transparently with Silverlight.
The first script-tag runs dlr-<releasedate>.js
which sets up a hidden Silverlight control on the page to download IronRuby and run any Ruby script-tags. The IronRuby binaries are downloaded to the browser cache, so they are not re-downloaded for any other application, unless the browser cache is cleared or is invalidated (Fig 2 and 3). These binaries set up the Silverlight control to process Ruby script-tags and execute them with IronRuby.
Note: IronRuby is not currently part of the Silverlight installation because keeping IronRuby open-source is a priority, and Silverlight is a closed-source project. The ability to download the binaries on the first load lets IronRuby stay as a separate project.
The specification for how all this works is in the Silverlight - Back to Just-Text paper; it is also a great source of documentation for the IronRuby-specific features, over and above what Silverlight already provides.
It's worth pointing out that the entire application is just text; Silverlight IronRuby applications are made up of script-tags which have inline ruby code, or point to a ruby file on the Web server, along with other supported file-types referenced by script-tags to use vector graphics, archives of Ruby libraries (like the Ruby standard library, or a Gem), or even .NET assemblies.
Vector Graphics
A similar "Hello, World" example can be done with Silverlight's vector-graphics as well:
The vector-graphics markup is called XAML, providing a simple XML-based markup language for defining any vector-graphics, like a user-interface. However, visual elements defined with XAML can also be defined through code; for example that <TextBlock>
tag could have also been created from Ruby code, so you can decide to use XAML or just Ruby code to build vector-graphics:
t = TextBlock.new
t.name, t.text, t.font_size = "message", "Loading ...", 14
XAML is useful as there are great designer tools like Expression Blend which generate XAML that is directly consumable by Silverlight. However, if designers-tools aren't your thing, the Magic library provides a very clean Ruby DSL for building user-interfaces.
In-Browser Ruby Console
A lot of Ruby development happens at an interactive Ruby command-prompt, and there is no exception with running Ruby in the browser. Turning on the Ruby command-prompt is simple; just enable the "console" setting for this page, and a Ruby command-prompt will appear at the bottom of the page, letting you run code against the active application:
document.message
represents the DOM element with the id property of message
(document.get_element_by_id("message")
also works) and the click
DOM event is hooked with the block, which changes the innerHTML
of the clicked element. You can play around with code in this console window, and then when your satisfied move it into the actual HTML file.
Everything in Silverlight is usable through Ruby, just like it was originally written in Ruby. The is possible because IronRuby is directly integrated with the CLR. For example, you can see what methods are on the first DOM object in the HTML body by using normal Ruby idioms. For more information on what APIs are available in Silverlight, see the Full Silverlight 3 Documentation.
2D Drawing
A good way to get acquainted with new technology is to focus on an area and have some fun; here I'll be using the 2D drawing libraries in Silverlight to make some "art". The first example is ruby-squares.html, which draws 200 randomly size and randomly colored squares.
However, that's not all the Ruby code running in the app; in the HTML file you'll notice four script-tags before the code shown above. These files provide various helpers for working with Silverlight from Ruby.
repl.rb
provides a way of enabling the command window through code, along with controlling when it's visible based on the query-string (ruby-square.html
doesn't show the console at all, ruby-square.html?console
will open the IronRuby Console panel, and ruby-square.html?console=off
show the console with all panels hidden).
wpf_ext.rb
contains some helpers to make dealing with Silverlight's graphics libraries nicer from Ruby. This is only a fraction of the functionality that wpf_ext.rb
normally provides, as this file was truncated for the article.
sketch.rb
sets up Silverlight for 2D drawing, calling those setup and draw methods described above at the appropriate times; largely influenced by ruby-processing.
bouncer.rb
bounce any Silverlight object around a Silverlight canvas; I'll use this directly in the drawings. To experiment with it, run $sketch.toggle_bounce
from the command-window to begin bouncing all the objects on the screen around. You can also re-run $sketch.setup
to add more objects:
Speaking of ruby-processing, ruby-circles.html is one of the ruby-processing examples which I showed running in a Windows desktop app at RubyConf 2009, but can also run on the Mac through Silverlight.
Flickr Photo Viewer
While 2D animations are a fun way of exploring Ruby in the browser, they don't really capture what making a "real-world" client-side web application would be like, with more standard user-interactions like clicking links and typing into text boxes. A simple Flickr photo viewer should do the trick though; using Flickr's Web service to search for images and displaying them on the page:
The first thing this application needs to do is react when the "search" button is pressed. Ruby blocks (as well as procs) are used to handle events from the HTML page:
The create_request
method takes the text in the textbox and makes a Web request to the appropriate Flickr Web service URL. When the request is complete, the applications shows the images Flickr returned:
The show_images
method parses the response from Flickr into Ruby objects, and then the application's view render the photos with ERB:
view.rb - rendering HTML from ERB templates
images.erb - an ERB template which creates HTML for displaying Flickr images
The erb
method uses the exact same ERB that is part of the Ruby standard library, and what Rails uses by default in views. The ability to run the same libraries, such as ERB, or even your own application code, on both the client and the server is unique way of being "DRY". It can help to blur the line between your client and server code, since everything can be written in Ruby, and open up new ways of sharing code and being productive.
Learn More
I hope this article has inspired you to look at using IronRuby for your next project, be it in the browser or not. Here are more resources to get you going with IronRuby in the browser:
jimmy.thinking - My blog has a bunch of tutorials on some interesting things that can be done with Silverlight and IronRuby, including Testing with Ruby and Embedding IronRuby in existing applications (though that article is for a native windows application, the same principles apply to the browser). Also, if you just want an update of IronRuby in general, my latest blog entry about the project's status from RubyConf 2009 has all the latest information, as well as the other posts in that series.
Documentation PDF - Paper about how the IronRuby in Silverlight integration works.
ironruby.com/browser - Placeholder website for IronRuby in the browser; it currently has a redistributable download and some simple samples. Content from Gestalt's website is currently under transition to this site, but the samples on that site are still relevant, as well as the newly released Gestalt Widget Pack, built on the latest version of IronRuby.
Full Silverlight 3 Documentation - Covers everything you can do with Silverlight 3. Examples are in C# or VB.NET, but are straight-forward to convert to Ruby.
github.com/ironruby/ironruby - IronRuby source code; Silverlight specific sources are all here. You can open bugs on the CodePlex project page.
And when in doubt, contact the IronRuby mailing list - you can also post online through ruby-forum.
April 1, 2010 at 1:32 pm
This was a very nice article. BTW, do you need a local webserver, or could you just open the html file in your browser straight from the file system? I wasn't clear on what the webserver was providing.
April 1, 2010 at 1:36 pm
Very impressive.
April 1, 2010 at 1:45 pm
You had me at <script type="text/ruby :)
April 1, 2010 at 1:57 pm
@Brandon: Because of this:
And this will not run direct from the file system due to Silverlight's security sandbox, so make sure you access it through a Web server.
Some Flash apps have a similar issue I've found..
I can't help Windows users, but on Linux and OS X you can run this from a folder to have it work as an HTTP server on localhost:8000:
python -c "import SimpleHTTPServer;SimpleHTTPServer.test()"
April 1, 2010 at 9:23 pm
You had me at:
You had me at <script type="text/ruby
...but lost my interest at:
Silverlight
...because of:
the concept of an open web
April 2, 2010 at 4:15 am
Thanks for the nice comments and support!
@peter and @brandon: though a web-server is required today, we're looking into ways in making just the html file opened from the file-system work as well; I believe if we limit the downloading of external files from the file-system things will work ... but that still means that will only work from a web-server.
@grimen: if you don't feel comfortable using Silverlight because it's not open-source, you can always use the open-source implementation called Moonlight: http://www.go-mono.com/moonlight/
April 2, 2010 at 4:17 am
... slight correction: the last sentence in the @peter/@brandon reply should read "... but that still means that external scripts (script src="foo.rb") will only work from a web-server.
April 2, 2010 at 9:22 am
@grimen very true. especially when you're using a closed source mac.
April 2, 2010 at 11:05 am
@Puss Boots: The Web is a totally different layer to the operating system. With an open, functional Web, it doesn't matter so much if user systems are closed source or not.
April 9, 2010 at 4:32 pm
FYI, The "Ruby says hello" code on Github doesn't quite tally with the picture in the main article: this
should, I think, read
April 9, 2010 at 4:33 pm
D'Oh. Let's try that again without embedding script HTML tags...
%lt;script src="ironruby/dlr.js" type="text/javascript"%gt;%lt;/script%gt;
should perhaps be changed to
%lt;script src="http://gestalt.ironruby.net/dlr-latest.js" type="text/javascript"%gt;%lt;/script%gt;
April 9, 2010 at 4:34 pm
D'oh * 2. Time to go home. One last try, this time with feeling...
<script src="ironruby/dlr.js" type="text/javascript"></script>
<script src="http://gestalt.ironruby.net/dlr-latest.js" type="text/javascript"></script>
April 11, 2010 at 3:36 am
Ruby! In the browser! I'm off to install silverli...BAH! Well played, microsoft. Well played.
Still a bad idea. Try again silverlight. You evil temptress you.