SlideShare a Scribd company logo
Arel and Rails 3
Relational algebra meets ActiveRecord
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.
Operators
      Primitive             Derived
  Selection (WHERE)      Set Intersection
  Projection (SELECT)       Division
      Cross Join           Natural Join
      Set Union
    Set Difference
Rename (SELECT A as B)
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
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
Arel in Action
> (syd_pubs & squire).all

This causes ActiveRecord::Relation to ask Arel to build the SQL
query 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')
Grouping and sorting data
  > pubs_beers = Pub.joins(:beers)
  > pubs = pubs_beers.select('pubs.name, count(*) as
beers_count').group('pubs.name')

 > pubs.all[0].beers_count
 # 2

  > pubs.order('beers_count').all
Range Conditions
> today = Time.now.at_beginning_of_day
> tomorrow = Time.now.tomorrow.at_beginning_of_day
> Pub.where(:created_at => today..tomorrow).all

Arel 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')
Scopes: Reusable Relations
class Beer < ActiveRecord::Base
  scope :stout, where(:flavor => "Stout")
end


> Beer.stout.all
# gives back an Array with the results
Eager Loading Associations
Associations 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 )
Eager Loading Associations
Eager load what you need using the new relations syntax:

> pubs = Pub.includes(:beers).all
> pubs[0].beers
> pubs[1].beers

Note 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))
Thank you!
Q&A
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

More Related Content

Similar to Arel in Rails 3 (17)

PPTX
3_1-_Chapterehehhsbsbsbsbdbdbdbdbdbdbdndndndndnđbbđnnd_2_-_Relational_Model_O...
T207TrnVnt
 
PDF
What\'s new in Rails 2.1
Keith Pitty
 
PPT
Relational Algebra
guest20b0b3
 
DOCX
database-querry-student-note
Leerpiny Makouach
 
PPTX
Using Mysql.pptx
StephenEfange3
 
PPTX
Oracle basic queries
PRAKHAR JHA
 
PDF
1.1 Intro to WinDDI.pdf
ssuser8b6c85
 
PPT
04.SQL.ppt
suchithreddyvemula
 
PDF
Migration from mysql to elasticsearch
Ryosuke Nakamura
 
PDF
Sequel
LittleBIGRuby
 
PDF
Tour of Ecto March 2017 Dave Lucia
David Lucia
 
PDF
Market Basket Analysis in R
Rsquared Academy
 
KEY
What's new and great in Rails 3 - Matt Gauger - Milwaukee Ruby Users Group De...
Matt Gauger
 
PDF
MySQL for beginners
Saeid Zebardast
 
ZIP
Ruby on Rails: Tasty Burgers
Aaron Patterson
 
PPT
INTRODUCTION TO SQL QUERIES REALTED BRIEF
VADAPALLYPRAVEENKUMA1
 
3_1-_Chapterehehhsbsbsbsbdbdbdbdbdbdbdndndndndnđbbđnnd_2_-_Relational_Model_O...
T207TrnVnt
 
What\'s new in Rails 2.1
Keith Pitty
 
Relational Algebra
guest20b0b3
 
database-querry-student-note
Leerpiny Makouach
 
Using Mysql.pptx
StephenEfange3
 
Oracle basic queries
PRAKHAR JHA
 
1.1 Intro to WinDDI.pdf
ssuser8b6c85
 
04.SQL.ppt
suchithreddyvemula
 
Migration from mysql to elasticsearch
Ryosuke Nakamura
 
Tour of Ecto March 2017 Dave Lucia
David Lucia
 
Market Basket Analysis in R
Rsquared Academy
 
What's new and great in Rails 3 - Matt Gauger - Milwaukee Ruby Users Group De...
Matt Gauger
 
MySQL for beginners
Saeid Zebardast
 
Ruby on Rails: Tasty Burgers
Aaron Patterson
 
INTRODUCTION TO SQL QUERIES REALTED BRIEF
VADAPALLYPRAVEENKUMA1
 

More from Leonardo Borges (15)

PDF
Realtime collaboration with Clojure - EuroClojure - Barcelona, 2015
Leonardo Borges
 
PDF
Parametricity - #cljsyd - May, 2015
Leonardo Borges
 
PDF
From Java to Parellel Clojure - Clojure South 2019
Leonardo Borges
 
PDF
The algebra of library design
Leonardo Borges
 
PDF
Futures e abstração - QCon São Paulo 2015
Leonardo Borges
 
PDF
Functional Reactive Programming / Compositional Event Systems
Leonardo Borges
 
PDF
High Performance web apps in Om, React and ClojureScript
Leonardo Borges
 
PDF
Programação functional reativa: lidando com código assíncrono
Leonardo Borges
 
PDF
Monads in Clojure
Leonardo Borges
 
PDF
Clojure Macros Workshop: LambdaJam 2013 / CUFP 2013
Leonardo Borges
 
PDF
Intro to Clojure's core.async
Leonardo Borges
 
PDF
Functional Reactive Programming in Clojurescript
Leonardo Borges
 
PDF
Clojure Reducers / clj-syd Aug 2012
Leonardo Borges
 
PDF
The many facets of code reuse in JavaScript
Leonardo Borges
 
PDF
Continuation Passing Style and Macros in Clojure - Jan 2012
Leonardo Borges
 
Realtime collaboration with Clojure - EuroClojure - Barcelona, 2015
Leonardo Borges
 
Parametricity - #cljsyd - May, 2015
Leonardo Borges
 
From Java to Parellel Clojure - Clojure South 2019
Leonardo Borges
 
The algebra of library design
Leonardo Borges
 
Futures e abstração - QCon São Paulo 2015
Leonardo Borges
 
Functional Reactive Programming / Compositional Event Systems
Leonardo Borges
 
High Performance web apps in Om, React and ClojureScript
Leonardo Borges
 
Programação functional reativa: lidando com código assíncrono
Leonardo Borges
 
Monads in Clojure
Leonardo Borges
 
Clojure Macros Workshop: LambdaJam 2013 / CUFP 2013
Leonardo Borges
 
Intro to Clojure's core.async
Leonardo Borges
 
Functional Reactive Programming in Clojurescript
Leonardo Borges
 
Clojure Reducers / clj-syd Aug 2012
Leonardo Borges
 
The many facets of code reuse in JavaScript
Leonardo Borges
 
Continuation Passing Style and Macros in Clojure - Jan 2012
Leonardo Borges
 
Ad

Arel in Rails 3

  • 1. Arel and Rails 3 Relational algebra meets ActiveRecord
  • 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. Operators Primitive Derived Selection (WHERE) Set Intersection Projection (SELECT) Division Cross Join Natural Join Set Union Set Difference Rename (SELECT A as B)
  • 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. 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. Arel in Action > (syd_pubs & squire).all This causes ActiveRecord::Relation to ask Arel to build the SQL query 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. Grouping and sorting data > pubs_beers = Pub.joins(:beers) > pubs = pubs_beers.select('pubs.name, count(*) as beers_count').group('pubs.name') > pubs.all[0].beers_count # 2 > pubs.order('beers_count').all
  • 8. Range Conditions > today = Time.now.at_beginning_of_day > tomorrow = Time.now.tomorrow.at_beginning_of_day > Pub.where(:created_at => today..tomorrow).all Arel 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. Scopes: Reusable Relations class Beer < ActiveRecord::Base scope :stout, where(:flavor => "Stout") end > Beer.stout.all # gives back an Array with the results
  • 10. Eager Loading Associations Associations 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. Eager Loading Associations Eager load what you need using the new relations syntax: > pubs = Pub.includes(:beers).all > pubs[0].beers > pubs[1].beers Note 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))
  • 13. Q&A
  • 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

Editor's Notes