ruby-on-railsrubyassociationsrails-activerecordhas-many

Is there a way to create a has_many association that just filters items from another has_many association?


Basically I have a has_many association. I want to create another association that just filters items from the original association.

class Track
  belongs_to :playlist
end

class Playlist
  has_many :tracks

  has_many :five_start_tracks, -> { what to write here? }
  has_many :long_tracks, -> { ... }
end

Is there a way to do it or I should just go with

def five_star_tracks
  tracks.where(rating: 5)
end
def long_tracks
  tracks.where("duration_seconds > ?", 600)
end

Solution

  • Yes, you can add scopes to has_many associations. But you have to add the class name to the association too, because Ruby on Rails is not able to guess it from the name anymore.

    class Playlist
      has_many :tracks
    
      has_many :five_start_tracks, -> { where(rating: 5) }, class_name: 'Track'
      has_many :long_tracks, -> { where('duration_seconds > ?', 600) }, class_name: 'Track'
    end
    

    Or with_options which might increase readability when you define longer lists of specialized associations:

    class Playlist
      has_many :tracks
    
      with_options class_name: 'Track' do
        has_many :five_start_tracks, -> { where(rating: 5) }
        has_many :long_tracks, -> { where('duration_seconds > ?', 600) }
      end
    end