Living on the edge (of Rails) #5 - better eager loading and more
Another week of edge Rails changes, featured on the Rails Envy podcast. This weeks’ report covers changes from 21 Jan 2008 to 27 Jan 2008 (the day the Rails Envy podcast was recorded).
Eager loading :includes does pre-loading
The current gem Rails behavior when loading associations with something like
Author.find(:all, :include => [:posts, :comments])
is to make a big query with multiple joins that fetches all the associations in the same query (for you RDBMS geeks, the "cartesian product").
Frederick Cheung (fcheung on the Rails Trac) has contributed an impressive optimization to this by pre-loading the associations rather than trying to eager loading with one big query. So a find like this:
Author.find(:all, :include => [:posts, :comments])
would first load all the authors, then all the posts, and then all the comments in 3 smaller, faster queries.
The main benefit of this (depending on your data): Running X simple queries (to fetch authors, then posts and comments) rather than one mega-query that joins all the associated tables is faster most of the time. The result set is often smaller as well.
More details can be found at ticket #9640 on the Rails Trac.
Related changeset: http://dev.rubyonrails.org/changeset/8672
composed_of aggregations can now be used in finder conditions
You can now use value objects that you've previously specified that your model is composed_of in the finder conditions hash. E.g. if you have a Customer that has a balance aggregation:
class Customer < ActiveRecord::Base
composed_of :balance, :class_name => "Money", :mapping => %w(balance amount)
end
You can now pass a Money value object to Customer#find:
Customer.find(:all, :conditions => { :balance => Money.new(20, "USD") })
Convenient.
Related changeset: http://dev.rubyonrails.org/changeset/8671
New helper: label_tag
A label_tag helper has been missing for quite awhile since the label helper was added. No longer:
label_tag 'name'
# => <label for="name">Name</label>
label_tag 'name', 'Your name'
# => <label for="name">Your name</label>
Related changeset: http://dev.rubyonrails.org/changeset/8685
New ActiveSupport class: ActiveSupport::TimeWithZone
A new ActiveSupport::TimeWithZone class has been introduced to make timezone support in Rails easier. Ryan Daigle has a good writeup on this.
A word of warning though: this is still work in progress, as Geoff Buesing, the core team member responsible for these timezone changes, has more to add on how his plans for the timezone puzzle in the comments.
Related changeset: http://dev.rubyonrails.org/changeset/8696
map.root can be easily aliased
map.root now accept a single symbol as an argument to declare an alias. Just a little something to keep your routes a little more DRY, e.g.:
map.new_session :controller => 'sessions', :action => 'new'
map.root :new_session
Related changeset: http://dev.rubyonrails.org/changeset/8738
As usual, let me know of any inaccuracies or any suggestions you may have in the comments!