Skip to main content

Using Named Scopes Across Models with ActiveRecord#Merge

Ce795239ba5dd2384fc2f88ffaff5451
Chris Oliver May 15, 2014
 


After years of working with ActiveRecord and watching it change so much, it is exciting to find new features you didn't know about. The one I discovered this week is ActiveRecord#merge. It is one of the most underused methods in ActiveRecord, due in part, to the name. It isn't necessarily clear what they mean by "merge" but it's simply a way of using a named scope on a joined model.

Say we have two models that are associated and one of them has a scope:

class Author < ActiveRecord::Base
  has_many :books
end
class Book < ActiveRecord::Base
  belongs_to :author

  scope :available, ->{ where(available: true) }
end

Let's say we want to join the tables to find all Authors who have books that are available. Without ActiveRecord#merge, we have to make this query:

Author.joins(:books).where("books.available = ?", true)
SELECT "authors".* FROM "authors" INNER JOIN "books" ON "books"."author_id" = "authors"."id" WHERE "books"."available" = 't'

But with ActiveRecord#merge, this becomes a whole lot cleaner and we don't duplicate the available scope:

Author.joins(:books).merge(Book.available)
SELECT "authors".* FROM "authors" INNER JOIN "books" ON "books"."author_id" = "authors"."id" WHERE "books"."available" = 't'

As you can see, the resulting SQL queries are exactly the same. ActiveRecord#merge is a great way to reduce the duplication in your code to continue relying on the named scopes you define in your models. I really want to see more people using this so please share this around!

Want to learn more about Rails and become a great programmer?

Check out the Ruby on Rails Screencasts for more awesome learning material like this.

P.S. You might enjoy following me on Twitter.


Loading...

Latest from the blog

Start building fast, modern Rails websites in no time with GoRails tutorials.

Subscribe to the newsletter

Join 18,000+ developers who get early access to new screencasts, articles, guides, updates, and more.

By clicking this button, you agree to the GoRails Terms of Service and Privacy Policy.

More of a social being? We're also on Twitter and YouTube.