Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom scope on has_many, :through association (Rails 4)

CONTEXT:

In my setup Users have many Communities through CommunityUser, and Communities have many Posts through CommunityPost. If follows then, that Users have many Posts through Communities.

User.rb

has_many :community_users
has_many :communities, through: :community_users
has_many :posts, through: :communities

Given the above User.rb, Calling "current_user.posts" returns posts with one or more communities in common with current_user.

QUESTION:

I'm looking to refine that association so that calling "current_user.posts" returns only those posts whose communities are a complete subset of the current_user's communities.

So, given a current_user with community_ids of [1,2,3], calling "current_user.posts" would yield only those posts whose "community_ids" array is either 1, [2], [3], [1,2], [1,3], [2,3], or [1,2,3].

I've been researching scopes here, but can't seem to pinpoint how to accomplish this successfully...

like image 371
neon Avatar asked May 17 '14 22:05

neon


1 Answers

Nice question...

My immediate thoughts:

--

ActiveRecord Association Extension

These basically allow you to create a series of methods for associations, allowing you to determine specific criteria, like this:

#app/models/user.rb
has_many :communities, through: :community_users
has_many :posts, through: :communities do
   def in_community
       where("community_ids IN (?)", user.community_ids)
   end
end

--

Conditional Association

You could use conditions in your association, like so:

#app/models/user.rb
has_many :posts, -> { where("id IN (?)", user.community_ids) }, through: :communities #-> I believe the model object (I.E user) is available in the association

--

Source

I originally thought this would be your best bet, but looking at it more deeply, I think it's only if you want to use a different association name

Specifies the source association name used by has_many :through queries. Only use it if the name cannot be inferred from the association. has_many :subscribers, through: :subscriptions will look for either :subscribers or :subscriber on Subscription, unless a :source is given.


Being honest, this is one of those questions which needs some thought

Firstly, how are you storing / calling the community_ids array? Is it stored in the db directly, or is it accessed through the ActiveRecord method Model.association_ids?

Looking forward to helping you further!

like image 195
Richard Peck Avatar answered Nov 13 '22 19:11

Richard Peck