Upcoming SlideShare
×

# Arel in Rails 3

11,979 views
11,770 views

Published on

4 Likes
Statistics
Notes
• Full Name
Comment goes here.

Are you sure you want to Yes No
• Be the first to comment

Views
Total views
11,979
On SlideShare
0
From Embeds
0
Number of Embeds
507
Actions
Shares
0
58
0
Likes
4
Embeds 0
No embeds

No notes for slide
• \n
• \n
• \n
• \n
• \n
• \n
• \n
• \n
• \n
• \n
• \n
• \n
• \n
• \n
• ### Arel in Rails 3

1. 1. Arel and Rails 3Relational algebra meets ActiveRecord
2. 2. What!?• Relational Algebra deals with sets of ﬁnite relations, which are closed under certain operators. These operators operate on one or more relations to yield a relation.• Relation (table) - Data structure composed of a heading (columns) and an unordered set of tuples (rows) that share the same type.• Closure - A set is said to be closed under some operation if the result of that operation is a member of the set. • e.g.: Real numbers are closed under subtraction but natural numbers are not. Although 3 and 7 are natural numbers the result of 3 - 7 is not.
3. 3. Operators Primitive Derived Selection (WHERE) Set Intersection Projection (SELECT) Division Cross Join Natural Join Set Union Set DifferenceRename (SELECT A as B)
4. 4. ActiveRecord::Relation Example Pub.select(:name).where(:city => Sydney) #yields an ActiveRecord::Relation instance. No SQL ran. but prior to Rails 3...Pub.find(:all, :select => "name", :conditions => { :city => Sydney }) #yields an Array with the results
5. 5. Ok, but now what?Build more interesting queries by combining relations...> syd_pubs = Pub.select(pubs.name).where(:city => Sydney)> squire = Pub.joins(:beers).where(:beers => {:name => James Squire})Now get me all the pubs in sydney that sell James Squire!> (syd_pubs & squire).all# yields an Array
6. 6. Arel in Action> (syd_pubs & squire).allThis causes ActiveRecord::Relation to ask Arel to build the SQLquery below, corresponding to the combined relations: SELECT pubs.name FROM pubs INNER JOIN beers_pubs ON beers_pubs.pub_id = pubs.id INNER JOIN beers ON beers.id = beers_pubs.beer_id WHERE (pubs.city = Sydney) AND (beers.name = James Squire)
7. 7. Grouping and sorting data > pubs_beers = Pub.joins(:beers) > pubs = pubs_beers.select(pubs.name, count(*) asbeers_count).group(pubs.name) > pubs.all[0].beers_count # 2 > pubs.order(beers_count).all
8. 8. Range Conditions> today = Time.now.at_beginning_of_day> tomorrow = Time.now.tomorrow.at_beginning_of_day> Pub.where(:created_at => today..tomorrow).allArel takes care of ranges as well... SELECT pubs.* FROM pubs WHERE (pubs.created_at BETWEEN 2010-10-05 00:00:00.000000 AND 2010-10-06 00:00:00.000000)
9. 9. Scopes: Reusable Relationsclass Beer < ActiveRecord::Base scope :stout, where(:flavor => "Stout")end> Beer.stout.all# gives back an Array with the results
10. 10. Eager Loading AssociationsAssociations are lazily loaded by default and as such...> pubs = Pub.all> pubs[0].beers> pubs[1].beers...produces these queries to be executed: SELECT pubs.* FROM pubs SELECT * FROM beers INNER JOIN beers_pubs ON beers.id = beers_pubs.beer_id WHERE (beers_pubs.pub_id = 1 ) SELECT * FROM beers INNER JOIN beers_pubs ON beers.id = beers_pubs.beer_id WHERE (beers_pubs.pub_id = 2 )
11. 11. Eager Loading AssociationsEager load what you need using the new relations syntax:> pubs = Pub.includes(:beers).all> pubs[0].beers> pubs[1].beersNote that only one query is used to load the Beers info: SELECT pubs.* FROM pubs SELECT beers.*, t0.pub_id as the_parent_record_id FROM beers INNER JOIN beers_pubs t0 ON beers.id = t0.beer_id WHERE (t0.pub_id IN (1,2,3))
12. 12. Thank you!
13. 13. Q&A
14. 14. References• Arel - http://github.com/rails/arel• Rails - http://github.com/rails/rails• Rails Guides - http://guides.rubyonrails.org/• Relational Algebra - http://en.wikipedia.org/wiki/Relational_algebra