Search code examples
rubyassociationsmodels

Association Exclude Based on Field


I'm looking for the best Ruby way to accomplish this.

I have a Person that has_many Feeds through Subscriptions. So we can do things like Person.feeds, and it gets all the feeds a person is subscribed to.

Problem is, subscriptions are either authorized or deauthorized. What is the best way to make Person.feeds respect the Authorized status bit on the Subscription model?

So we can do something like Person.feeds.where(:status => authorized).


Solution

  • You can call this with a command like the following:

    @person.feeds.joins(:subscription).where(subscriptions: { status: 'authorized' })
    

    N.B. the joins takes the association's format, singular in this case, while where takes the table name, typically pluralised.

    What this does in order is:

    • Loads the feeds belonging to a person
    • Joins these feeds to their subscription
    • Queries the subscriptions table to return only the feeds where the subscription is active

    To refactor this, I'd include a couple of methods in the relevant models:

    # feed.rb
    scope :active, -> { joins(:subscription).where(subscriptions: { status: 'authorized' }) } 
    
    # person.rb
    def active_feeds
      feeds.active
    end
    

    Then, you can just call @person.active_feeds to get the results you want from anywhere in your code base.

    (There's also the added bonus of Feed.active being available anywhere should you wish to display active feeds outside of a user's scope.)

    Hope that helps - let me know if you've any questions.