Rails & Active Record: how to join tables that are only related through another table?

时间:2016-10-20 19:39:42

标签: ruby-on-rails activerecord

I am trying to build an active record query using through table associations. Here are my models:

Event.rb:

has_many :event_keywords

User.rb:

has_many :user_keywords

Keyword.rb:

has_many :event_keywords
has_many :user_keywords

EventKeyword.rb:

belongs_to :event
belongs_to :keyword

UserKeyword.rb:

belongs_to :user
belongs_to :keyword

I am trying to build an Event scope that takes a user_id as a param and returns all the Events with shared keywords. This was my attempt but it's not recognizing the user_keywords association:

 scope :with_keywords_in_common, ->(user_id) {
     joins(:event_keywords).joins(:user_keywords)
     .where("user_keywords.user_id = ?", user_id)
     .where("event_keywords.keyword_id = user_keywords.keyword_id")
  }

How do I resolve this?

2 个答案:

答案 0 :(得分:1)

Something like this might work. 2-step process. First, get all user's keywords. Then find all events with the same keyword.

scope :with_keywords_in_common, ->(user) {
  joins(:event_keywords).
    where("event_keywords.keyword_id" => user.user_keywords.pluck(:id))
}

答案 1 :(得分:0)

The database seems to be overkill here and firstly I'd simplify by making keywords polymorphic, this would get rid of 2 of your tables here (event_keywords, and user_keywords).

Your associations would then look like this:

# Event.rb:
has_many :keywords, as: keywordable

# User.rb:
has_many :keywords, as: keywordable

# Keyword.rb:
belongs_to :keywordable, polymorphic: true

And finally, your scope:

scope :with_keywords_in_common, -> (user_id) do
  joins(:keywords)
  .where('keywords.keywordable_type = User AND keywords.word IN (?)', keywords.pluck(:name))
end