Skip to main content

Using Named Scopes Across Models with ActiveRecord#Merge Discussion

General • Asked by Chris Oliver

Gravatar
Alex Alex (10 XP) on

You have to fix your latest blog Post excerpt on the home page.
Great site btw.

Gravatar
Chris Oliver (159,850 XP) on

Doh! I'll get on that. My markdown parser sure didn't like that video.


Gravatar
Leung Ho Kuen on

I am doing it with subquery
Like

Author.where(id: Book.available.select(:author_id))

I agree that your version is cleaner and easier to remember,
but you might want to add .distinct after joins to avoid duplicated authors.

Gravatar
Chris Oliver (159,850 XP) on

Ah yes, great points! I like that as a subquery and definitely need the distinct for my example as well.

Gravatar
Văn Lý Vũ on

this query will generate a long SQL query. it's not best practice.


Gravatar
Victor Rodrigues (10 XP) on

Well, this is useful, but ugly... Thinking about querying, im not supposed to "merge" anything. IMHO

My wish was Author.books.scope(:available), lol

Gravatar
Chris Oliver (159,850 XP) on

Well you can do Author.books.available because that's just querying Book.where(author_id: X).available. But obviously this is for the more complex joining tables case, so at least you're working with the models like you normally would. Not the best, but it saves you from duplication.

Gravatar
Ryan Johnson on

The difference is that Author.books.available will return books, but Author.joins(:books).merge(Book.available) will return authors. Using merge is useful when your desired record set has conditions that are dependant on another table. As stated in the video, you're looking for **Authors** with available books, not available **books**.

Gravatar
Văn Lý Vũ on

Nice guys.


Gravatar
Blake Thomson on

Minor nitpick: but I really think you mean `ActiveRecord::Relation#merge`, not `ActiveRecord#merge`


Gravatar

Gravatar
Renan Gurgel (40 XP) on

Something wrong with the video :/

Gravatar
Chris Oliver (159,850 XP) on

Fixed!

Gravatar

Gravatar
godie mendoza on

great! is ugly, but useful, thanks!


Gravatar
bodaonline on

Big thanks! Had a default scope on my Model but rails 4.2.5 didn't unscope it when I was doing "each do" so using the .joins(:model).merge(Model.scope) you suggested instead


Gravatar
Nicholas Thompson on

Could do something like:

scope :has_available_books, -> { joins(:books).merge(Book.available) }

Then you could just do:

Author.has_available_books


Gravatar
Konstantin Ivanov on

Need to note that merges on the same attribute overrides each other.

class Book < ActiveRecord::Base
...
scope :red, ->{ where(color: "red") }
scope :green, ->{ where(color: "green") }
end

Author.joins(:books).merge(Book.red).merge(Book.green)
^ would apply only green, because overwrite previous merge


Login or create an account to join the conversation.