Skip to content

Instantly share code, notes, and snippets.

@slayer
Forked from goodmike/Arel Multi-join example.rb
Created February 23, 2011 23:04
Show Gist options
  • Save slayer/841395 to your computer and use it in GitHub Desktop.
Save slayer/841395 to your computer and use it in GitHub Desktop.
# The problem: In your Rails 3 project, you have a model Request that models a
# user's request for content related to a specific problem or topic. The user
# can tag her request with any number of words. These are modeled by a Tag class
# backed by a tags DB table. Since you want unique records per tag, you have a
# Tagging class backed by a taggings table. Taggings is a a many-to-many table
# with some additional information. Also, other models in the application
# besides requests can be tagged: The Tagging class defines a polymorphic
# relationship "taggable" with those models.
#
# So pretty soon you want to look up all the requests that are tagged with
# certain words, say "bunnies" and "bacon".
#
# You can do that with raw SQL:
Request.find_by_sql("
SELECT * FROM requests
INNER JOIN taggings ON taggings.taggable_id = requests.id AND taggings.taggable_type = 'Request'
INNER JOIN tags ON taggings.tag_id = tags.id
WHERE tags.contents = 'bunnies' OR tags.contents = 'bacon'
")
# But you are using Rails 3. You have Arel. So how do you do the chained inner
# joins from requests to taggings and then taggings to tags?
# With Arel
Request.joins(:taggings).
where(:taggings => {
:id => Tagging.joins(:tag).
where(:tags => {:contents => ["bunnies","bacon"]})
})
# You probably do not want duplicate Request records
Request.joins(:taggings).
where(:taggings => {
:id => Tagging.joins(:tag).
where(:tags => {:contents => ["bunnies","bacon"]})
}).uniq
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment