November 18, 2010
Rails 3: New features & Changes
By Michel Golffed
In this post I’ll show you some basic examples about the new features and changes of the web framework Rails 3, for this I’ll use two models: User and Task, having a relationship between them where a User has_many :tasks.
ActiveRecord finder methods
Let’s start by finding the five most recently created users:
Rails 2
1 |
User.find(:all, : order => "created_at desc", :limit => 5) |
What’s new about this method call in rails 3?
Rails 3 looks at the hash of options that is being passed to find(:all, : order, and :limit) and replace each item in the hash with an equivalent method.
New API methods:
where, having, select, group, order, limit, offset, joins, includes, …
So, in Rails 3 this becomes:
1 |
User.order("created_at desc").limit(5) |
Let’s continue with this second example:
Rails 2:
1 |
User.find(:all, :conditions => ["created_at <= ?", Time.now], :include => :tasks) |
Rails 3:
1 |
User.where("created_at <= ?", Time.now).includes(:tasks) |
In this example the “where” method substitutes the :conditions parameter.
Named Scopes
Changes to named_scopes in Rails 3:
User model in rails 2 with two named scopes:
1 2 3 4 5 |
class User < ActiveRecord::Base named_scope :active, :conditions => '!is_deleted' named_scope :south_american, :conditions => ["nationality IN (?)", Nationality::south_american_countries] end |
The same in rails 3 would be:
1 2 3 4 5 |
class User < ActiveRecord::Base scope :active, where('!is_deleted') scope :south_american, where("nationality IN (?)", Nationality::south_american_countries) end |
Note that the method that we use to define as named_scope has become to just “scope”. Also, we no longer pass the conditions as a hash but, as with find, we use methods.
Chainability
Another new feature is the ability to build up scopes. If we want to create a scope called “recent”, that will return the most recently created active south american users ordered by their creation date, we can do so by reusing the two scopes we already have.
Chaining together the two scopes we already have and add an order method to create the new scope, is all we need to do.
Here is the result:
1 |
scope :recent, active.south_american.order("created_at desc") |
ActiveRecord Validation
Separate validations in Rails 2
1 2 3 |
validates_presence_of :email validates_uniqueness_of :email validates_length_of :email, :maximum => 30 |
All validations together for a field in Rails 3
1 2 3 |
validates :email, :presence => true, :uniqueness => true, :length => {:maximum => 30} |
Hope you enjoyed it, some other features of Rails 3 will be published on upcoming posts.