bigpotato
bigpotato

Reputation: 27517

Rails: has_many through with multiple foreign keys?

I have 2 tables and a join table:

Model 1:

class Book < ActiveRecord::Base
  has_many :book_people
  has_many :illustrators, through: :book_people, class_name: 'ComaPerson', foreign_key: 'illustrator_id'
  has_many :authors, through: :book_people, class_name: 'ComaPerson', foreign_key: 'author_id'

Join table:

class BookPerson < ActiveRecord::Base
  belongs_to :book
  belongs_to :illustrator, class_name: 'ComaPerson', foreign_key: 'illustrator_id'
  belongs_to :author, class_name: 'ComaPerson', foreign_key: 'author_id'

Model 2 (the one giving me issues):

class ComaPerson < ActiveRecord::Base
  has_many :book_people #<-- not working
  has_many :books, :through => :book_people

My test is failing because it says that the BookPerson model does not have a coma_person_id column:

Failures:

  1) ComaPerson should have many book_people
     Failure/Error: it { should have_many(:book_people) }
       Expected ComaPerson to have a has_many association called book_people (BookPerson does not have a coma_person_id foreign key.)
     # ./spec/models/coma_person_spec.rb:5:in `block (2 levels) in <top (required)>'

Since ComaPerson can be either an illustrator or author, I used illustrator_id and author_id in the join table, so the join table has three columns 'book_id, illustrator_id, and author_id'. Does that mean I have to add a coma_person_id column to the join table for it to work?

Upvotes: 0

Views: 926

Answers (1)

bigpotato
bigpotato

Reputation: 27517

I think I figured it out. So you have to mask the has_many :join_table_name and split them into two, one for each foreign_key, while specifying what the model name and foreign key are.

class ComaPerson < ActiveRecord::Base
  has_many :authored_books_people, class_name: 'BookPerson', foreign_key: 'author_id'
  has_many :illustrated_book_people, class_name: 'BookPerson', foreign_key: 'illustrator_id'
  has_many :authored_books, through: :authored_books_people, primary_key: 'author_id', source: :book
  has_many :illustrated_books, through: :illustrated_book_people, primary_key: 'illustrator_id', source: :book

Upvotes: 2

Related Questions