Archive for the 'Ruby' Category

Giles Screencast on Seaside and Rails

For those who may not be on the Seaside mailing list, Giles just posted a couple of screencasts about Seaside and Rails. If you’re a Rails guy, go watch them, you’ll learn something about Seaside. If you’re a Seaside guy, watch them to learn a little about the Rails approach. In either case, go watch them, the second one especially, it’s an excellent screencast. This may be a preview of something he might present as OSCON 2007. My favorite quote from the video…

“Although I love Rails, I’m going to find a way to do stuff in Seaside as quickly as I can, because it’s just so cool.”

Seems people are starting to understand that having the power to write desktop style applications (i.e. insanely complex) on the web might be something worth having. I think the Seaside community is going to have quite a few Rails converts over the next year or two. Ruby seems to be a gateway drug to Smalltalk and Rails I think, will be the gateway drug to Seaside.

Rails vs Seaside

Sometimes a small sample is really helpful in showing the differences between two approaches. Ruby on Rails is a slick web framework for building web applications the old way. When I say the old way, I mean building URLs manually and passing parameters through query strings manually, i.e. marshaling session data manually.

Rails automatically maps URLs to controllers and methods in those controllers to setup the appropriate models, and automatically binds the correct view for that method, based on naming conventions of the files. It’s a great method and saves much of the hassle of writing a web app while enforcing a nice model view controller paradigm. Here’s a sample any Rails programmer will probably recognize, first list.rhtml…

<% @recipes.each do |recipe| %>
  <tr>
   <td><%= link_to recipe.title, :action => “edit”, :id => recipe.id %></td>
   <td><%= recipe.category.name %></td>
   <td><%= recipe.date %></td>
  </tr>
<% end %>
<p><%= link_to "Create new recipe", :action => “new” %></p>

and its controller…

class RecipieController < ApplicationController
    def list
        @recipies = Recipie.find(:all)
    end

    def edit
        @recipie = Recipie.find(@params[:id])
    end
end

Nice and clean, but the programmer is still working in a template language, requiring constant context switching between Ruby and HTML, and still manually building anchor tag URLs by calling a method and passing in the recipe’s id. Passing around ids requires that the next view, bound to the edit method in the controller, needs to look up the object from the database with that id from reading the request parameters. You can see this in the edit method of the controller, it sets up data in an instance variable in the controller so the view will have access to it.

This is classic web development done very cleanly, and honestly very Smalltalk’ish, however, passing around an object id isn’t very object oriented (it’s rather relational actually), and context switching between two languages while working in the view isn’t very fun. Instead of passing around an objects id why not pass around the object instead?

Enter Seaside, same code, different approach, more object oriented…

renderListOn: html
    self recipes do: [:recipe |
        self renderRecipe: recipe on: html ].

    html paragraph:
        [html anchor
            callback:[self editRecipe: Recipe new];
            with: ‘Create new Recipe’]

renderRecipe: aRecipe on: html
    html tableRow id: #recipie, aRecipe id; with:
            [html tableData:
                [html anchor
                    callback:[self editRecipe: aRecipe];
                    with: aRecipe title];
                tableData: aRecipe category name;
                tableData: aRecipe date ]

and the controller code…

recipies
    ^recipes ifNil:[recipes := Recipe findAll]

editRecipe: aRecipe
    self call: (RecipeEditor for: aRecipe)

Seaside puts the view and controller together in one class, the component, and it can do so cleanly because there is no templating language, rendering views are simply method calls in pure Smalltalk. So instead of having a controller, with a bunch of RHTML files and partials, we have components (aka view/controllers), with rendering methods (aka partial views).

It’s important to note however, that view code and controller code are still normally kept quite separate and organized using Smalltalk’s method categories. View methods are normally categorized as “rendering”, or something more specific like “rendering ajax”, while controller code is categorized in categories like “actions”, “queries”, “accessing”, or whatever categories you make up to keep your code organized. This is one of those Smalltalk things that no other language really has, and only exists in its environment so it doesn’t translate to sample code.

Now, the main thing to note here, is that objects are passed between views as actual objects using a constructor on the view (RecipeEditor for: recipe). One component simply creates and calls another. The components are also rendered in pure Smalltalk, which means they can be factored into smaller more reusable methods (aka partials), using all of Smalltalk’s existing tools, i.e. the refactoring browser. This is amazingly productive.

The anchor tag has a closure attached to it via its #callback: method, containing the actual code we want to execute when the user clicks the link. This closure, or block as Smalltalkers call them, gets turned into a URL automatically by Seaside and stored as a continuation on the current session. This means that RecipieEditor view doesn’t need to go back to the database and look up the recipe by its id, because it was given the actual recipe object directly (less load on the database). In essence, instead of passing a bunch of state through a URL manually, you simply say when this link is pressed, execute this code. This is a technique discussed by Paul Graham in his essay Beating the Averages that he used in ViaWeb. This one change drastically changes the way one thinks about, and builds, web applications and makes programming much simpler.

Notice how I’ve factored out the rendering of a single row into its own method. This sets me up to do some nice simple Ajax updates of individual row by being able to pass an Ajax rendering canvas through that same #renderRecipeOn: method. For example, I could re-render just that row, via Ajax, when a hyper link is clicked with just this…

html anchor
    onClick: (html updater id: #recipe, self randomRecipe id;
                    callback:[:ajax | self renderRecipe: self randomRecipe on: ajax]);
    with: ‘Replace random recipe with another random recipe’

So when I write a page, I break it up into rendering methods based on which parts of the screen I want to update via Ajax. This is similar to what Rails does with partials, except Seaside does it with ordinary objects and methods. Top to bottom, objects and method calls in pure Smalltalk, no web stuff.

This is what Seaside gives you, complete abstraction of the http request response cycle so you can program normally, as you would any desktop application, without all the extra hassles that web development introduced. Even abstracting away JavaScript for the most part. This translates into much faster application development, yes, even faster than Rails. It also means if you have to port a desktop application to the web, Seaside may allow you to do so without having to completely rework the existing design.

The price you pay… sessions and a little memory on the server. Yes it’s harder to scale than a session-less approach like Rails, but it will scale, and memory is cheap these days, far cheaper than programmers. Seaside, like Rails, is a very opinionated framework. Seaside’s opinion is that programming is the most expensive part of application development, so let’s optimize development time instead of CPU memory and cycles and throw out the (stateless/templated html) model of web development in favor of simpler web development in one language, where you have all of your tools available and aren’t constantly context switching between several languages.

Rails vs Seaside From a Java Developer

Here’s an interesting post from a Java guy trying to decide between Ruby on Rails and Seaside. He has quite a few interesting things to say concerning the shortcomings of Ruby on Rails, and how well Seaside handles that complexity with ease.

He also has a few complaints about Seaside, most of them valid. Seaside still isn’t the full stack solution that Ruby on Rails is. We still have to handle object relational mapping, something Ruby on Rails gives you for free. Nor does Seaside deal with object validation and errors, I use Magritte for this. Magritte rocks, but I’m not sure the average guy trying out Seaside will find it, or learn how to use it. From an outside point of view, Ruby on Rails looks like a much more complete solution.

We have Glorp, which can do this, but only against Postgres Sql in Squeak. Nothing against Postgres, but seriously, in the real business world, it’s either Microsoft Sql Server or Oracle; and it’s also usually a legacy database, so we really need something like Glorp for those databases, because something like ActiveRecord is just too brain dead to work.

Most of the schemas I have to work with suck, and can’t be changed because people used the database as an integration point for multiple apps (God I’m tired of seeing people make this mistake). Doing a simple class = table, object = row mapping just doesn’t cut the mustard for legacy development against existing databases.

Seaside is far more advanced than Ruby on Rails, and is a much better web framework for doing anything complex, but we’re still missing the market on CRUD apps. CRUD against a popular business database is still far too difficult using Squeak. I’m sure Visualworks has far better database support, but I want something free… I want Squeak, I want Squeak to work with Sql Server, I want a Pony… :(

Featured Resources

There are different programming languages for different purposes. For advertising the one that has the best features becomes bit difficult as they usually have their own purposes to fulfill. Similar competition applies to the hosting companies, like ipowerweb, or another best one would be dot5hosting to choose from. With the cheap internet phones comes the cheap call rates. Taking a 350-001 test got easier with preparation guides available online.

Seaside and Smalltalk Interest Spreading

Here’s a nice quote from a Java/Ruby programmer’s recent blog entry on Seaside…

Frameworks like Struts or Webwork tries to model this kind of flow in static XML configuration files, which is at best, a hack. Rails tries to do this in its own code by convention, which is a good attempt but the way Seaside does it is the best I’ve seen so far.

That’s the kind of thing I like to see because I still think Seaside is the Smalltalk killer app. If Smalltalk is going to come back into the mainstream, Seaside is going to be the vehicle of that change.

Next Page »