Christopher Miles
Christopher Miles

Reputation: 89

How to create different types of has_many :through relationships with two models?

I have two models, Person and Business, and a join table.

class Person < ActiveRecord::Base
  has_many :person_businesses
  has_many :businesses, through: :person_businesses
end

class Business < ActiveRecord::Base
  has_many :person_businesses
  has_many :people, through: :person_businesses
end

class PersonBusiness < ActiveRecord::Base
  belongs_to :person
  belongs_to :business
end

I want there to be more than one way to associate a business and a person, though. For instance, a business can have a person as an employee and as a customer.

How would I go about modeling this?

I considered adding a column to person_businesses named role, which would be an enum corresponding to what the relationship type is but I still don't know how to write the relationship.

Upvotes: 2

Views: 218

Answers (1)

Christopher Miles
Christopher Miles

Reputation: 89

So I think I found an answer to my question. I got most of this from this answer with a few changes.

class Business < ActiveRecord::Base
  has_many :person_businesses
  has_many :people, through: :person_businesses
end

class Person < ActiveRecord::Base
  has_many :person_businesses
  has_many :employees, through: :employee_businesses, source: :business
  has_many :employee_businesses, -> { where(person_type: 'employee') }, class_name: 'PersonBusiness'
  has_many :customers, through: :customer_businesses, source: :business
  has_many :customer_businesses, -> { where(business_type: 'customer') }, class_name: 'PersonBusiness'
end

class PersonBusiness < ActiveRecord::Base
  enum person_type: { employee: 0, customer: 1 }
  belongs_to :person
  belongs_to :business
end

This works for now, but it doesn't look like it's easily extendable. If anyone has any suggestions on how to simplify it I would love to see it.

Edit:

I've continued working on this problem and have a simpler setup. I also changed the condition because using where with an enum was causing it to always return 0 (more information for those that are interested).

class Business < ActiveRecord::Base
  has_many :person_businesses
  has_many :people, through: :person_businesses
end

class Person < ActiveRecord::Base
  has_many :person_businesses
  has_many :employees, -> { PersonBusiness.employee }, through: :person_businesses, source: :business
  has_many :customers, -> { PersonBusiness.customer }, through: :person_businesses, source: :business
end

class PersonBusiness < ActiveRecord::Base
  enum person_type: { employee: 0, customer: 1 }
  belongs_to :person
  belongs_to :business
end

Upvotes: 2

Related Questions