I still remember with pleasure that December 23, 2008 in which David Heinemeier Hansson announced that the Merb team would merge with that of Rails to give life to the third version of the framework. Since then more than 365 days and more than 4000 commits have passed on the official Ruby on Rails repository, 250 people have contributed to a precise and pragmatic refactoring that has optimized all the deficient aspects of the previous version until the release of the 3.0 beta version of the 5 February.

But what has changed in Rails 3.0?

The greatest effort in creating this release has been focused on transforming Rails from a slow and interdependent set of libraries to a fast and agnostic framework, capable of exposing a set of APIs that each component correctly implements.

Take for example the criticized elitist relationship between ActiveRecord and ActionPack; in Rails 2.0 they talk without any abstraction mechanism, one invoking the other’s methods, making it extremely difficult to replace one of the two libraries (for example DataMapper instead of ActiveRecord).

In the 3.0 version of the framework, a new ‘ActiveModel’ object has been wisely inserted that incorporates the communication specifications and that any ORM can include obtaining instantaneously (or almost) the privilege of an interview with ActionPack.

Not wanting to reduce the article to a sequence of changes made to Rails 3.0 let’s try to test the main ones on a small test application; To do this, let’s get first of all a working copy of the framework beta by typing from the command line (Ruby 1.8.7 is needed):

<pre class=”brush: php; html-script: true”>
gem install tzinfo i18n builder memcache-client rack
rack-mount rack-mount racket erubis mail text-format \
thor bundler
gem install rails –pre
</pre>

We conclude the introduction of this article by creating a Rails 3.0 application with the most classic set of commands:

<pre class=”brush: php; html-script: true”>
rails showcase_3_0
</pre>

Rails 3: manage dependencies among the gems

One of the most annoying aspects of running a Rails 2.x application was the lack of efficiency in the vendor method of addictions; if you remember the list of requested gems it had to be done inside the ‘config / environment.rb’ file with this syntax:

<pre class=”brush: php; html-script: true”>
config.gem “bj”
config.gem “aws-s3”,: lib => “aws / s3″
</pre>

which inevitably led to the problem ‘what happens if a specific gem is needed before the application calls the file environment.rb?’.

A striking example in this sense is constituted by ‘ rack ‘, a vital component to the functioning of the framework and necessary well before the initialization routine. Version 3.0 of Rails solves the problem by delegating dependency management to a gem: ‘ bundler ‘ which at this point becomes the only one to be installed a priori on the computer.

Bundler reads instructions on which gems to install within the file Gemfilein the root folder of each Rails 3.0 application; for example, showcase_3_0let ‘s open up and examine the content:

<pre class=”brush: php; html-script: true”>
# I removed the commented instructions
source ‘http://gemcutter.org’
gem “rails”, “3.0.0.beta”
gem “sqlite3-ruby”,: require => “sqlite3″
</pre>

it is clear that at this moment the only dependencies required are towards version 3.0 of the framework and the adapter to the default database, sqlite.

Assuming we have received showcase_3_0via email in a compressed archive, all we need to do to align our environment with the application’s specifics is to execute the commands in the root of the environment:

<pre class=”brush: php; html-script: true”>
bundle install
</pre>

The gem, following the instructions of the file just examined, would populate a folder of convenience (usually within the home of the user who launched the procedure) with all the dependencies required, taking care to include this folder in the application load paths and relieving us from tedious setup procedures.

If instead we had to distribute what we created we should not do anything else but type:

<pre class=”brush: php; html-script: true”>
bundle pack
</pre>

to include the individual files .gemthat make up the dependency tree, specified in Gemfile, within the vendor/cache application folder; this route is, in fact, the first to be scanned by bundlers in search of gems during the command install.

In the second part of the article: structuring the queries with the relational algebra and the improvements under the RESTful profile.

Arel and relational algebra

Great news for ActiveRecord 3.0 : the ORM abandons its syntax to evolve towards an even more flexible and intuitive structuring by embracing Arel, a gem that implements the concept of relational algebra. But, what is relational algebra?

The ‘algebra’ name brings us to operators who all know and use daily: I speak of the classic symbols +, -, /, etc. that applied to the system of real numbers contribute to define the so-called elementary algebra. The term relational algebra indicates that in this case the operators insist not on the set R but on that of the relations; therefore the relational algebra describes a query as a succession of operations on the set of relations.

Take for example the very simple SQL fragment:

<pre class=”brush: php; html-script: true”>
SELECT * FROM pals
LEFT JOIN countries on countries.id = pals.country_id
WHERE pals.age> 10
</pre>

its counterpart in relational algebra is as follows:

Implementing this mechanism Arel makes it possible to concatenate in an intuitive and transparent way an indefinite number of operators (selection, join, ordering, etc.) by embarking on the computational cost of their translation into SQL.

To test this feature, we create the objects Paland Countryin showcase_3_0taking advantage of the opportunity even to notice the small changes in the syntax of the build commands:

<pre class=”brush: php; html-script: true”>
rails generate model Pal name: string country_id: integer
rails generate model Country name: string
</pre>

Now modify the file db/seeds.rbto specify some default values of the countries table by inserting:

<pre class=”brush: php; html-script: true”>
countries.create ([{: name => ‘Italy’}, {: name => ‘France’}, {: name => ‘Spain’}])
</pre>

We define the relationship (1, n)between countriesand pals, acting on the respective files in the folder app/modelsas follows:

file country.rb

<pre class=”brush: php; html-script: true”>
class Country <ActiveRecord :: Base
has_many: pals
end
</pre>

pal.rb file

<pre class=”brush: php; html-script: true”>
class Pal <ActiveRecord :: Base
belongs_to: country
end
</pre>

Now we launch the usual commands for creating and populating the database:

<pre class=”brush: php; html-script: true”>
rake db: create && rake db: migrate && rake db: seed
</pre>

At this point we can invoke the console and experiment a bit ‘the possibilities offered by the new ActiveRecord API:

<pre class=”brush: php; html-script: true”>
rails console # to launch the console

>> Pal.create [{: name => ‘Sandro’,: country_id => 1}, {: name => ‘Francesca’,: country_id => 1}, {: name => ‘Alberto’,: country_id = >} 2]
=> [# <Pal id: 2, name: “Sandro”, country_id: 1, created_at: …
>> Pal.where (: country_id => 1)
=> # <ActiveRecord :: Relation: 0x1032350d8 @scope_for …
>> Pal.where (: country_id => 1) .all
=> [# <Pal id: 2, name: “Sandro”, country_id: 1, …
>> Pal.where (: country_id => 1) .to_sql
=> “SELECT \” pals \ “. * FROM \” pals \ “WHERE (\” pals \ “. \” Country_id \ “= 1)”
>> Pal.joins (: country) .where (: countries => {: name => ‘Italy’}). Order (: name) .all
=> [# <Pal id: 3, name: “Francesca”, country_id: 1, created_at: …
</pre>

The query generation mechanism, benefiting from Arel’s support, allows to link an indefinite number of operations among them; moreover, as long as no iteration (ex:) eachor collection method is invoked on this chain (ex all:), the return object is always of the type ActiveRecord::Relationand therefore subject to new concatenations.

Finally, it is possible at any time to know the shape of the resulting SQL by invoking the method on the chain to_sql.

With these little experiments we have explored a small portion of the benefits of this new syntax that in the coming months will make querying the databases even simpler and more flexible; for those who are carrying a port of a 2.x application, I remember finally that the old approach is still usable even if ‘deprecated’.

Rails 3: the RESTful paradigm

More REST in Rails

Rails 3.0 makes some substantial changes to the syntax of routese renders; the aim is to exploit even more the conventions inherent in the RESTful paradigm to reduce the necessary lines of code. It often happens that, by writing an application with Rails 2.x, almost every action of each controller ends with a respond_tomore or less complex, as in the following example:

<pre class=”brush: php; html-script: true”>
def index
@users = User.all
respond_to do | format |
format.html
format.xml {render: xml => @users}
format.json {render: json => @users}
end
end
</pre>

To overcome this the new version of the framework introduces the method respond_withthat does nothing more than apply a conventional behavior based on some factors such as the verb with which the request was made, the presence or absence of errors, the type of output format required , etc. For example, the above code translates into:

<pre class=”brush: php; html-script: true”>
def index
@users = User.all
respond_with (@users)
end
</pre>

while a classic creation action can be implemented in this way:

<pre class=”brush: php; html-script: true”>
def create
@user = User.new (params [: user])
flash [: notice] = ‘User successfully created’ if @ user.save
respond_with (@user)
end
</pre>

Notice how the two calls that conclude the two functions are exactly the same respond_with(@user):; the magic happens in fact inside the class ActionController::Responder, invoked by the function respond_with, where specific methods for each format intervene using conventions to establish the correct reaction against the available information. Take for example the classic HTML format and inspect the operation:

<pre class=”brush: php; html-script: true”>
def to_html
default_render
rescue ActionView :: MissingTemplate => e
navigation_behavior (s)
end

def navigation_behavior (error)
if get?
raise error
elsif has_errors? && default_action
render: action => default_action
else
redirect_to resource_location
end
end
</pre>

the function to_htmlfirst tries to execute the template associated with the current action, if it fails (for example because there is no template, as in the create actions) it invokes the function navigation_behaviorthat behaves as follows:

  • if the call verb GETis an exception is launched (because every action called in get should result in rendering a template on the screen)
  • if instead there are errors inside the resource (in our case @user) the default action is rendered ( edit.html.erbfor the verb PUTand new.html.erbfor the POST)
  • in the event that neither of the above two conditions is satisfied, the script redirects the action indexof the current controller

Clearly it is possible to modify this convention , for example by operating as in the following example, which takes the code written previously, but forcing redirect to a page to our pleasure (in the case of HTML):

<pre class=”brush: php; html-script: true”>
def create
@user = User.new (params [: user])
flash [: notice] = ‘User successfully created’ if @ user.save
respond_with (@user) do | format |
format.html {redirect_to users_url}
end
end
</pre>

Rails 3: ActionPack and ActiveModel

Candies

There are still so many things I have not mentioned that have changed in this new release; among these the two main ones are called SafeBuffere ActiveModel. Suppose we want to include the following code fragment in a view:

<pre class=”brush: php; html-script: true”>
<% = “Greeting <b> all </ b> the readers of html.it”%>
</pre>

By doing it unexpectedly we would get this result:

<pre class=”brush: php; html-script: true”>
Greeting <b> all </ b> the readers of html.it
</pre>

This is because since version 3.0 Rails automatically escapes all strings that have not been previously marked as html_safe, the correct syntax to reach the result that we expect becomes therefore:

<pre class=”brush: php; html-script: true”>
<% = “Greeting <b> all </ b> the readers of html.it” .html_safe%>
</pre>

Of course we will not often find ourselves in the condition of forcing a string to html_safe, this because all the helpers of the framework already incorporate this feature.

Now let’s move on to the second feature: if you remember the introduction you should already have associated ActiveModel to that object which, if incorporated, guarantees the right to talk with ActionPack; another great advantage of this architectural choice is that of being able to include within simple classRuby methods once the patrimony of the only daughters of ActiveRecord::Base.

In the following list, for example, a Ruby class acquires the possibility to validate its own instance variables simply by including the module ActiveModel::Validations:

<pre class=”brush: php; html-script: true”>
# dog.rb file
class Dog # note the absence of ActiveRecord :: Base
includes ActiveModel :: Validations # include only the validation component

validates_presence_of: age
attr_accessor: age
def initialize (age)
@age = age
end
end
</pre>

Conclusions

I hope to have succeeded in this article to give an overview of the immense amount of new features and paradigms implemented in version 3.0 of Ruby on Rails. Personally I believe that this release has all the credentials to redefine a new quality standard in terms of the framework for Web applications as long as it proves to have maintained, despite the heavy refactoring, all the stability of previous versions.

LEAVE A REPLY

Please enter your comment!
Please enter your name here