Reputation: 22663
I have a Rails app with users, suggestions and searches. There is a many-to-many association between users and searches such that each user can be in many searches and each search can have many users (called "searchers").
Users can make suggestions into each Search they are a member of. Thus, each Suggestion belongs to a User and a Search.
class Suggestion < ActiveRecord::Base
belongs_to :suggester, class_name: 'User'
belongs_to :search
end
class Search < ActiveRecord::Base
# ... user-search associations.
has_many :suggestions
end
class User < ActiveRecord::Base
# ... user-search associations.
has_many :suggestions, foreign_key: :suggester_id
end
Now, I'm trying to allow users to favorite suggestions which are made into searches they are a member of. The snag is that user's can favorite suggestions which were made by team mates as well as suggestions which they made themselves. This means that favoriting cannot be accomplished via a simple favorite
attribute on Suggestion
.
I have tried to make Favorite
a join model between User and Suggestion.
class Favorite < ActiveRecord::Base
belongs_to :user
belongs_to :suggestion
end
However, I am having trouble accessing the suggestions which have been favorited by a particular user from within a particular search. For example:
class Search < ActiveRecord::Base
has_many :suggestions
def suggestions_favoured_by(user)
# here I need to grab the search's suggestions and then scope them
# down to only these that have an entry in the favorites table which
# has user_id == user.id.
# That seems ridiculously complicated.
end
end
The only way I can think to solve this problem is to add a search_id
attribute to Favorite
. However, that would de-normalize my favorites table because a favorite belongs to a suggestion which belongs to a search, and a favorite also belongs to a search directly.
The only other idea that I can think of (and I haven't tried to implement this yet, I'm having trouble visualizing where it's going to lead me in my head) is that the user - favorite association should happen through the join model between User and Search, rather than on the User and Search models seperately (because that would de-normalize the table).
Whats the best way to architect this?
My apologies for the long-winded nature of the question.
Upvotes: 0
Views: 171
Reputation: 13926
You can do this with a scope, without implementing a suggestions_favoured_by
method that would do the filtering manually.
class Suggestion < ActiveRecord::Base
has_many :favorites
scope :favoured_by, lambda { |user_id|
joins(:favorites).
where(:favorites => {:user_id => user_id})
}
end
Then to access a User's favorite suggestions for a particular search
:
search.suggestions.favoured_by(user_id)
Rails will take care of building the SQL query, and your associations stay normalized.
Upvotes: 1