neanderslob
neanderslob

Reputation: 2693

Rails belongs_to one of two models

I'm working with two different models Person and Organization. Among many other attributes, both a Person and Organization can be a Contractor. If I was working with just the Person model and wanted to store contractor information I would say that Contractor belongs_to :person and be done with it. However this seems like Contractor belongs to two other models.

I searched around on google and found a lot of info about how to assign ownership to two different models at once. (For example a Sale must belong to both a Buyer and a Seller.) But in my situation a Contractor is EITHER a Person or an Organization. Is there any way to elegantly store Contractor information for both models in the same table?

If not, I figure I can always make two different contractor tables, but I figured this might be an opportunity to learn something. Many thanks in advance.

Upvotes: 3

Views: 1489

Answers (2)

I agree with ShallmentMo, but as additional, You could define something like this:

Models

class Contractor < ActiveRecord::Base
  belongs_to :contractable, polymorphic: true 
  ...
end

class Person < ActiveRecord::Base
  ...
  has_many :contractors, as: :contractable
  ...
end

class Organization < ActiveRecord::Base
  ...
  has_many :contractors, as: :contractable
  ...
end

Migrations

create_table :contractors , force: true do |t|
  t.references :contractable, polymorphic: true, index: true
  ...
  t.timestamps null: false    
end

Usage

  def create
    @contractor = Contractor.new(params[:contractor])
    contractable = params[:contractor][:contractable].split(":")
    @contractor.contractable_type = contractable[0] # String: 'Person' or 'Organization'
    @contractor.contractable_id = contractable[1].to_i # Integer: id of 'Person' or 'Organization'
    ...

Upvotes: 1

ShallmentMo
ShallmentMo

Reputation: 449

Maybe you can try this. Rails provide polymorphic-associtions. You can try to build one model named ContractorInfo belongs to Contractable(use polymorphic: true), then Person has_one ContractorInfo as contractable, Organization has_one ContractorInfo as Contractable.

Upvotes: 2

Related Questions