Archive for the tag 'Ruby'

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.

Objects, Classes, and Constructors, Smalltalk Style

Objects, classes, and constructors are an interesting thing in Smalltalk. Coming from languages like C#, Visual Basic, or Java, one expects to be able to declare constructors in your classes. You also expect them to be “special” nameless methods that can only be called by the “new” keyword when creating instances of your class. Smalltalk is different, and better, or worse, depending on your point of view.

Smalltalk is a language that “allows” one to write great code. It never feels like it gets in your way, however many things in Smalltalk are done by convention only, so it won’t “force” you to write great code.

Constructors in Smalltalk are simply a convention; the language has no “new” keyword. In Smalltalk, your classes themselves are objects, singletons in fact; they are the only instance of their meta class. This might sound weird, so lets look at an example. Say we declare a Person class

Object subclass: #Person
    instanceVariableNames: 'firstName lastName'
    category: 'OnSmalltalk'

First, notice that this is simply a method call on the object class (there is no special syntax for creating classes), which itself is an object. This creates two classes in the runtime image, one called “Person”, and one called “Person class”. The class “Person” is the sole instance of the class “Person class”. “Person class” is an instance of the class “Metaclass”.

So in Smalltalk for every class you create, an invisible parallel hierarchy of meta-classes is created. These meta-classes are referred to as the “class side” by Smalltalkers, and by the Smalltalk code browser.

The reason I mention all this is because these meta-classes commonly show up in other languages as the “Factory” pattern, a pattern all about object construction. This is important because it’s a great way to conceptualize the meta class, it’s the factory for creating instances of the class. To create an instance of our #Person, we do this…

person := Person new.

Notice, #new is a method on the “Person” class, rather than a keyword in the language. It’s simply an ordinary method that happens to be named #new. Unlike other languages, constructors in Smalltalk are nothing special, they’re simply any method that happens to create and return an instance of a class. Now, we could do this…

person := (Person new)
                  firstName: 'Ramon';
                  lastName: 'Leon';
                  yourself.

But a constructor would really help pretty this up and encapsulate the knowledge about what fields are required for construction rather that forcing the client to individually initialize the object and hoping he does it correctly. So let’s write a constructor for #Person, we’ll put it on the “Person class”, or the Person’s class side as it’d normally be called.

Person class>>firstName: aFirstName lastName: aLastName
    ^(self new)
        firstName: aFirstName ;
        lastName: aLastName;
        yourself.

Notice this is simply an ordinary method named #firstName:lastName on the Person’s meta class. It’s pretty much the same pattern as before, but calls “self new”, the default constructor inherited from its superclass. I can say self because this method is in the “Person class” It can be used like so…

person := Person firstName: 'Ramon' lastName: 'Leon'.

Much nicer now, a client no longer needs to know what arguments to initialize, he can simply call a constructor, more importantly, a named constructor, not an anonymous one like you’d see in most other languages. Consider the advantages of named constructors with an overly simplistic example (ignoring currency)…

someMoney := (Money dollars: 5) + (Money cents: 5).

Of course any real Smalltalk’er would do this by adding a few extension methods to a few Number classes and writing this instead…

someMoney := 5 dollars + 5 cents.

Also unlike “most” other languages, constructors, being ordinary methods in Smalltalk, can be inherited and overridden so subclasses need not redeclare the constructors of superclasses like C# and Java require.

Constructors are put into the method category “instance creation”. Finding constructors for a class is a simple matter of looking at the class side of any class, and looking in this category. If you find a constructor you want to use, highlight it, and press alt+n to see a list of all senders of this method, i.e. instant sample code.

On the instance side of a class, I could, if necessary, override #initialize which is automatically called by the default #new constructor. This is useful when you want to initialize your instance variables on object creation rather than lazily. For example…

Person>>initialize
    super initialize.
    relatives := Set new.

Some Smalltalk’ers prefer to write their constructors in a different style, one that enforces encapsulation a bit more, by not allowing public setters for all the instance variables, like so…

Person class>>firstName: aFirstName lastName: aLastName
    ^(self new)
        initializeFirstName: aFirstName lastName: aLastName;
        yourself.

Person>>initializeFirstName: aFirstName lastName: aLastName
    firstName := aFirstName.
    lastName := aLastName.
    relatives := Set new.

Personally, I don’t prefer this style, because it feels a bit repetitive creating essentially two constructors to avoid having public setters for your instance variables. This style feels like the author doesn’t trust me to not abuse the class, which doesn’t to me, feel like the Smalltalk spirit. It is however, in common use and you’ll see plenty of both of these styles in other peoples code.

Often, while growing a program, one will start without any constructors, doing inline cascaded initialization and only after using the class a bit, will you refactor a few examples into cleaner code using constructors.

To conclude, I hope you’ll notice from the sample code shown so far, everything is done using only objects, their instances, and their methods. There is no special syntax or keywords for creating classes or their constructors. In fact, there are only 6 reserved keywords in the entire Smalltalk language, self, super, nil, true, false, and thisContext. By comparison, Ruby has 38, Java has 52, C# about 76.

This should underline just how much more Smalltalk relies on pure OO and message passing rather than special language constructs. By being minimalist and only providing syntax for assignment, message passing, method return, and a few special literal notations for things like strings, arrays, numbers, and blocks, Smalltalk can be any language you want it to be. All of Smalltalk’s control and iteration structures are implemented in the library, as ordinary objects with ordinary methods. There’s simply no need for so many reserved words.

Smalltalk is not so much a language, as an extensible notation for creating languages. To rip off a famed martial artist, empty your mind, be formless, shapeless, like Smalltalk. If you put Smalltalk into a financial application, it becomes a custom finance language. You put Smalltalk into a shipping application, and it becomes a custom shipping language. Be Smalltalk my friend.

Oh, and to be fair, Smalltalk isn’t the only language with this quality, but it’s certainly my favorite. Languages that lack this quality, as far as I’m concerned, have no real future.

Featured Resources

The benefits of wireless internet are immense. Nonetheless are the upcoming domain names with a com domain being most sought after. For your domain web hosting, you will be able to get the best and cheap packages, thanks to the rising competition in this sector. With a simple email hosting, options vary. This whole efficient internet system runs on good dedicated servers that keep the ball rolling in the right direction.

A Smalltalk ActiveRecord using Magritte, Seaside, and Glorp

I’ve been working on a side project that’s given me reason to want to use Glorp with Seaside. Having just mapped the sample blog written from my screencast into Glorp manually, by writing Glorp descriptors, I decided that I wanted something simpler, something more like Ruby on Rails, automatic persistence, with almost no configuration.

Having used Magritte for a while to describe my Seaside UI’s, I decided that those same descriptions contained all the necessary meta data to write Glorp descriptions from. Unlike the ActiveRecord in Rails, or the one Alan Knight is working on, I’m not using the database as the source of my metadata, I’m using the objects themselves with meta data from Magritte instead.

I sat down and started hacking out my own ActiveRecord implementation, which is really just a small framework that glues these three existing frameworks together for me and makes using Seaside against a Postgres database easy for me. Needless to say, knowledge of Magritte is a prerequisite for using this code.

I just open sourced the code I’ve been using on SqueakSource, just add this repository to Monticello to get a copy

MCHttpRepository
    location: 'http://www.squeaksource.com/MagritteGlorp'
    user: ''
    password: ''

This is a first cut Alpha release, I make no guarantees, only the brave need attempt using it. To use it, simply requires the following.

subclass MGActiveRecord, this will be your root class, all your biz classes can descend from this.

MGActiveRecord subclass: #SBActiveRecord
	instanceVariableNames: ''
	classVariableNames: ''
	poolDictionaries: ''
	category: 'SeasideBlog-Glorp'

subclass MGDescriptorSystem and override #rootClass, returning the class above, like so…

rootClass
	^SBActiveRecord

and on the class side, override #defaultLogin

defaultLogin
    ^(Login new)
        database: PostgreSQLPlatform new;
        username: 'xxxx';
        password: 'xxxx';
        connectString: '127.0.0.1_yourDatabaseName'

and optionally #initializeDatabase: if you want to insert some test data on creation of the schema…

initializeDatabase: aSession
    aSession inUnitOfWorkDo: [aSession register: SBPost testPost]

Now, describe your classes with Magritte, here’s an example…

descriptionCategories
    ^ (MAMultipleOptionDescription selector: #categories label: 'Categories' priority: 1000)
        options: [SBCategory findAll execute] dynamicallyRefreshed ;
        classes:{SBCategory};
        reference: SBCategory description;
        componentClass: MACheckboxGroupComponent;
        yourself

[SBCategory findAll execute] dynamicallyRefreshed is a shortcut for (MADynamicObject on:[SBCategory findAll execute]) that I implemented, since Magritte descriptions are cached, I do this to ensure each time a UI is rendered, a fresh query is done against the database.

You must manually create your database in Postgres. Once created, to create your schema, simply call #createSchema on your MGDescriptorSystem subclass like so…

SBGlorpDescriptions createSchema.

It will use your default connection to infer and create the schema necessary to support your object model. I’ve only used this on two schemas so far, but it seems to work OK, though I’m sure there must be bugs.

Now, to use this all in Seaside, subclass MGGlorpSession and override #glorpDescriptionClass like so…

glorpDescriptionClass
    ^SBGlorpDescriptions

Once done, from Seaside, I can execute queries like so…

blogPosts
    "Grab published blog posts from database and return them in reverse order"

    ^(SBPost findAll)
        limit: self numberOfPostsToShow;
        where: [:each | each isPublished];
        orderBy: [:each | each timestamp descending];
        execute

And have the full power of Glorp available from two class methods, #find and #findAll which return Glorp queries wrapped in a decorator that allows you to call execute on them for the current Seaside context. All classes are commented. If anyone is brave enough to use this, I’d appreciate any feedback on any trouble you run into, or just general discussion about the approach. As I said before, I make no guarantees, but I’m using this code myself, and so far, it seems OK.

UPDATE: The tests included in the package are there to demonstrate a missing feature, automatic inheritance mapping. They do not need to be ran and have nothing to do with the base package. If createSchema works, you’re done, just start using it.

« Previous PageNext Page »