Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Arel in Rails 3


Published on

  • Be the first to comment

Arel in Rails 3

  1. 1. Arel and Rails 3Relational algebra meets ActiveRecord
  2. 2. What!?• Relational Algebra deals with sets of finite 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 => 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 = => 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 FROM pubs INNER JOIN beers_pubs ON beers_pubs.pub_id = INNER JOIN beers ON = beers_pubs.beer_id WHERE ( = Sydney) AND ( = James Squire)
  7. 7. Grouping and sorting data > pubs_beers = Pub.joins(:beers) > pubs =, count(*) asbeers_count).group( > pubs.all[0].beers_count # 2 > pubs.order(beers_count).all
  8. 8. Range Conditions> today => tomorrow => 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_pubs.beer_id WHERE (beers_pubs.pub_id = 1 ) SELECT * FROM beers INNER JOIN beers_pubs ON = 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 = t0.beer_id WHERE (t0.pub_id IN (1,2,3))
  12. 12. Thank you!
  13. 13. Q&A
  14. 14. References• Arel -• Rails -• Rails Guides -• Relational Algebra -