has many :through using defined scopes from the :through association instead of dupping

Hey all,

I’ve been doing a bunch of researching on this topic, and I wanted to get feedback from the community on this potential feature (or if I’m just completely missing that it’s already a feature, your gentle correction).

Recently, I’ve started a project, and I ran across a scenario where I had to introduce duplicate scoping while defining an association. :frowning:

Here’s a summary of the scenario: There is one model that has one scope and two associations to two other models. In one of the other models that the first “joining” model is associated with, I have a has_many association through this joined model. However, the complication (and duplication arises) that the association has to be scoped to the scope on the joining model. Currently (from what I’ve found through research), there’s no way to specify an existing scope on a :through association. The workaround is to create a scope on the has_many association that does the exact same thing that the :through association’s scope already does.

An example will probably help illuminate the problem:

Assume we have the following models definitions:

class Book < ActiveRecord::Base belongs_to :author, inverse_of: :books belongs_to :publication, inverse_of: :books

scope :published, → { where(is_published: true) }


class Author < ActiveRecord::Base has_many :books, inverse_of: :author has_many :publications, → { where(books: { is_published: true }) }, through: :books


class Publication < ActiveRecord::Base has_many :books, inverse_of: :publication



Notice the has_many :through association; this is currently how you’d have to manually scope the “publications” association to achieve the same effect of : publications = books.published.map(&:publication)


I’d like to write something similar to:

has_many :publications, through: { :books => :published }


Which would indicate: “Using the :books association, apply the :published scope, then retrieve all publications”.

Why this would be cool:

  1. Modularity
  2. Less duplication
  3. It would make at least me happy :smiley:

Some Research Links:

Related (but outdated) SO question

Related (but also outdated) topic here on the forum

I'd handle this with a specifically-named association (in `Author`):

has_many :published_books, -> { published }, class_name: 'Book' has_many :publications, through: :published_books

You may also want to look into the documentation for the `merge` method on Relation.

--Matt Jones