MIX10, Part 2.1 – Server-side web development with dynamic languages

26 Apr 2010

This post is part of the “MIX10 – Pumping Iron on the web” series:

The original post was mistakenly removed, so it’s been reposted with the original post date, 4/25/2010. Sorry if this confuses your blog readers or causes any other inconvenience.

One reason for embracing dynamic languages is to make your entire web-development experience simpler, be it on ASP.NET enabled web-servers, or on the client through Silverlight. Let's first look at the server.

Both IronPython and IronRuby can run on the same infrastructure as your ASP.NET applications, though in their own ways. Due to historic reasons, IronPython is supported as an ASP.NET language through the ASP.NET Dynamic Language integration, and IronRuby is supported through IronRuby.Rack, which enables Rack-based Ruby web-applications to run on ASP.NET. However, both are open-source, so each one could be ported to the other language.

Since these DLR-based languages run on ASP.NET, deploying them is no different than any other ASP.NET application; they can be run on any ASP.NET enabled web-server like IIS. Keeping that in mind, let’s first look at how simple Ruby web apps can be.

Minimal Ruby web-applications

Slide34

Ruby itself has very expressive syntax, and the Ruby community has built many web-frameworks to make web-development really simple. For example, Sinatra is a web-framework made to minimize the amount of code required to respond to web requests:

The above code does exactly what it says; when a get request happens for '/', show "Hello, World" on the page. This highlights Ruby's domain-specific language abilities; get looks like a keyword, though it's really just a method call with '/' as the first argument (Ruby lets you omit parenthesis from method calls too ... any VB script fans out there?). The do-end block is syntactic sugar for passing a lambda as the last-argument to the get method; all Ruby methods take an arbitrary "block" of code between do-end or {}. Inside that block is what happens on each request, and whatever is returned is written to the response ("Hello, World"); the last statement of any expression (blocks, methods, if-statements, etc) is implicitly the return value of the statement.

For all those C# fans, you can use curly-braces too:

Though these features sound arbitrary by themselves, if I were to write this with only the more-familiar language features found in Ruby, it would lose its character:

This defines a Ruby method verbose, which explicitly returns the string "Hello, World", and then calls the get method directly with the first argument being the URL and the second argument being an explicit pointer to the verbose method. Why does this look so much uglier? While this might be closer to how the programming language actually runs the initial examples, it's not how the programmer thinks.

Not to leave Python out of this love-fest, Python can make this look very pretty as well, but in her own special way. Imagining that a Sinatra-like library exists for Python:

Here the index method is created, which explicitly accepts both the request and the response as arguments; Python's all about being explicit, while Ruby is very implicit. Then the method would be "decorated" with the sinatra.get decorator, which would tell the web-framework that index represents a get-request for "/".

What's a decorator?

A Python decorator is basically a function that accepts a function and returns a function, so this imaginary Sinatra-like framework would define get something like this:

Another way of looking at it is without the decorator syntax:

It’s a bit more readable than Ruby, and almost equivalent to the decorator way, except for the order of get in the code. You'll also see that getting a method pointer is much cleaner than Ruby (index vs. method(:index)); in Ruby index would call the method, since Ruby allows method calls with or without parenthesis, where Python uses parenthesis to indicate a method call.

Point being is that both Ruby and Python are very expressive in their own ways, and makes it really easy to make simple websites on Windows. The IronRuby team takes of advantage of this to power http://ironruby.info, a Ruby-compatibility reporting website. This is the code from the main page:

This renders the index.haml template with the data returned from Stats.get_latest, which is pretty much what the code says. The HTML is generated from the haml templating engine, which makes generating HTML and calling Ruby code extremely easy:

To play around with using HAML, you can use aspnet-haml to support .haml files though ASP.NET.

Ruby on Rails - Databases with Ruby

Slide45

One of the most popular (or most buzzed) web-frameworks is Ruby on Rails, which is just a collection of Ruby libraries for structuring your web-application. Rails uses the Model-View-Controller pattern, so any ASP.NET MVC people will find it a very-familiar framework. However, Rails really shines when it comes to interacting with the database through it's ActiveRecord library (the “Model” layer). ActiveRecord maps Ruby classes to database tables, and provides an Ruby abstraction for interacting with the database:

This is all the code that is required to map your Ruby classes to the database, as well as create the structure of the database. ActiveRecord dynamically provides getters/setters for the table, as well as sets up foreign-keys and relationships based on conventions (belongs_to :posts assumes that the table has a 'post_id' field).

Interacting with the database is just as easy as calling methods; Post.all translates to the SELECT * from posts SQL query, since the Post object is mapped to the posts database table. Post.find(<id>) does a SELECT * from posts where id=<id>, etc.

Because Rails uses the Rack web-server interface, it will also run on IIS using IronRuby.Rack. See the IronRuby Rails documentation for more info about using Rails on IronRuby, and the Ruby on Rails documentation for general Rails usage.

ASP.NET MVC and IronRuby

Those were all Ruby-based web-frameworks, but what about using ASP.NET directly? The IronRuby community has developed an integration with ASP.NET MVC, so you can write your controllers and views in Ruby. Special thanks to Ivan Porto Carrero for single-handedly maintaining it.

ASP.NET and IronPython

Again, to give Python some love, IronPython directly integrates with ASP.NET, letting you write your ASPX code-behind files in Python.

Because of ASP.NET's events-based API (rather than a response-based API like Sinatra/Rails), Python methods can automatically hook events by using the <object>_<event-name> convention, and all server-side controls with "ID"s ends up being a variable available to the Python module. And application-level event hooks can go in global.py. But it's really nice to write Language="IronPython" at the top. =)

Python code can can also interact with the controls:

The <%# %> syntax lets run Python code in the context of the ASP.NET control's data source. The repeater's data-source was set to a list of IMAGETAGS (a python class), which has all those fields on it.

In conclusion, on the server you have many options for using IronRuby and IronPython to simplify your solutions.

Next up, using dynamic languages on the client through Silverlight.

comments powered by Disqus