Search code examples
ruby-on-railspolymorphic-associations

Rails polymorphic join has_many, through returns impossible SQL


I have 3 models set up as follows:

class User < ActiveRecord::Base

  has_many :interests, as: :interesting, dependent: :destroy
  has_many :games, through: :interests, source: :interesting, source_type: 'Game'
  has_many :people, through: :interests, source: :interesting, source_type: 'Person'

end

class Interest < ActiveRecord::Base

  belongs_to :interesting, polymorphic: true
  validates :user_id, presence: true
  validates :interesting_id, presence: true
end

class Game < ActiveRecord::Base
   has_many :users, through: :interests
   has_many :interests, as: :interesting
end

class Person < ActiveRecord::Base

  has_many :users, through: :interests
  has_many :interests, as: :interesting

end

When I try to call user.games the SQL run on the database is

SELECT "games".* FROM "games" 
INNER JOIN "interests" 
ON "game"."id" = "interests"."interesting_id" 
WHERE "interests"."interesting_id" = $1 AND
    "interests"."interesting_type" = $2 AND
    "interests"."interesting_type" = $3  
[["interesting_id", 3], 
["interesting_type", "User"], 
["interesting_type", "Game"]]

so obviously nothing is returned. The query should work, as long as ["interesting_type", "User"] isn't included.

What am I doing wrong? What is the best way to set up the User class as well as the Game and Person class?

I'm using Rails v4.2.6


Solution

  • So to summarize, the following appears to work in this use case:

    User < ActiveRecord::Base 
      has_many :interests, dependent: :destroy 
      has_many :games, through: :interests, 
               source: :interesting, source_type: 'Game'
      has_many :people, through: :interests, 
               source: :interesting, source_type: 'Person'
    
    end
    
    class Interest < ActiveRecord::Base
      belongs_to :user
      belongs_to :interesting, polymorphic: true
      validates :user_id, presence: true 
      validates :interesting_id, presence: true 
    end