Sergio Hernandez
Sergio Hernandez

Reputation: 181

ActiveRecord associations with two different models

I'm having a tough time wrapping my head around how I should be configuring my tables + associations.

I have a Lawsuit model. A lawsuit has_many parties (defendants, plaintiffs, attorneys, etc.). A party, in turn, can either be a Person or a Company. Ultimately, I want to be able to get:

This is how I have my tables + models set up currently:

people

| id | fname  | lname | date_of_birth |
| -- | ------ | ----- | ------------- |
|  1 | John   | Smith |    1974-02-04 |
|  2 | George | Glass |    1963-07-29 |

companies

| id | name      | duns      | ticker | address      |
| -- | --------- | --------- | ------ | ------------ |
|  1 | Acme Inc. | 239423243 | ACME   | 123 Main St. |

lawsuits

| id | jurisdiction | court | case_no    | title                       |
| -- | ------------ | ----- | ---------- | --------------------------- |
|  1 |      federal | SDNY  | 18-CV-1234 | Smith v. Glass, Acme, et al |

lawsuit_parties

| id | lawsuit_id | person_id | company_id | role      |
| -- | ---------- | --------- | ---------- | --------- |
|  1 |          1 |         1 |            | plaintiff |
|  2 |          1 |         2 |            | defendant |
|  3 |          1 |           |          1 | defendant |
# models/lawsuit.rb:
class Lawsuit < ApplicationRecord
    has_many :lawsuit_parties

    def parties
        self.lawsuit_parties
    end

    def defendants
        self.parties(where(lawsuit_parties: {role: 'defendant'})
    end

    def plaintiffs
        self.parties(where(lawsuit_parties: {role: 'plaintiff'})
    end

    def attorneys
        self.parties(where(lawsuit_parties: {role: 'attorney'})
    end
end
# models/lawsuit_party.rb
class LawsuitParty < ApplicationRecord
    belongs_to :person
    belongs_to :company
end
# models/person.rb
class Person < ApplicationRecord
    has_many :lawsuit_parties
    has_many :lawsuits, through: :lawsuit_parties
end
# models/company.rb
class Company < ApplicationRecord
    has_many :lawsuit_parties
    has_many :lawsuits, through: :lawsuit_parties
end

Any help you would be much appreciated…

Upvotes: 1

Views: 46

Answers (1)

danielricecodes
danielricecodes

Reputation: 3586

You're on the right track, but you'll need to introduce a polymorphic relationship onto your Join Model to get this type of modeling to work. An Enum can handle differentiating between Defendants and Plaintiffs, as well as provide several scopes/methods you're asking for for free.

class LawsuitParty < ApplicationRecord
    belongs_to :lawsuit
    belongs_to :partiable, polymorphic: true

    enum role: [:defendant, :plaintiff]
end

You'll need to write a migration to change your lawsuit_parties table to the following columns (all Rails convention names):

partiable_id   = Integer
partiable_type = String
role           = String

lawsuit_parties

| id | lawsuit_id | partiable_id | partiable_type | role      | 
| -- | ---------- | ------------ | -------------- | ----------|
|  1 |          1 |            1 | Person         | defendant |
|  2 |          1 |            2 | Company        | plaintiff |
|  3 |          1 |            1 | Company        | defendant |

Next, tell Rails that Person and Company records are associated with many Lawsuit's using has_many's :as option.

class Person < ApplicationRecord
    has_many :lawsuit_parties, as: :partiable
    has_many :lawsuits, through: :lawsuit_parties
end

Add the same has_many :lawsuit_parties, as: :partiable to Company, or any other models that may come later (i.e. Judge or JuryMember).

Once you have a LawsuitParty setup like this, you should be all set.

Upvotes: 3

Related Questions