2017-08-04 53 views
1

在我的進銷存應用程序invoices可以發送到companyperson。據我瞭解,這是Rails單表繼承(STI)的一個很好的用例。由於這兩種類型有許多共同的屬性和功能,我計算過,一個超一流的Recipient可能是一個很好的路要走:如何在Rails中爲單個表繼承建模人員和公司?

class Recipient < ActiveRecord::Base 
end 

class Company < Recipient 
    has_many :people 
end 

class Person < Recipient 
    belongs_to :company 
end 

我也明白,我需要在Recipient模型的屬性type

困擾我的唯一的事實是person可能(或可能不)屬於company。這怎麼可以在Rails中模擬?通常,我只需將另一個數據庫字段company_id添加到people表中。但是這裏只有一個表格(recipients)。那麼這怎麼做呢?

感謝您的任何幫助。

+1

另外值得一提的是用於製作公司和個人不同的模型完全關切,包括被稱爲(例如)可開票或不可開票或沿着這些行的擔憂,以保持發票邏輯。不過,STI在這裏也是一個很好的用例。讓我在一秒鐘內寫出答案,爲STI解決方案。 –

回答

1

的結構看起來是這樣的:

class Recipient < ActiveRecord::Base 
    has_many :invoices 
end 

class Company < Recipient 
    has_many :people 
end 

class Person < Recipient 
    belongs_to :company 
end 

class Invoice < ActiveRecord::Base 
    belongs_to :recipients 
end 

# Schema 
create_table "invoices", force: :cascade do |t| 
    t.integer "recipient_id" 
    t.datetime "created_at", null: false 
    t.datetime "updated_at", null: false 
    t.index ["recipient_id"], name: "index_invoices_on_recipient_id" 
end 

create_table "recipients", force: :cascade do |t| 
    t.integer "company_id" 
    t.string "type" 
    t.datetime "created_at", null: false 
    t.datetime "updated_at", null: false 
end 

我在控制檯只是嘗試:

> Recipient.all 
=> [#<Company:0x007fd55d797220 
    id: 1, 
    company_id: nil, 
    type: "Company", 
    created_at: Fri, 04 Aug 2017 10:57:41 UTC +00:00, 
    updated_at: Fri, 04 Aug 2017 10:57:41 UTC +00:00>, 
#<Person:0x007fd55d796730 
    id: 2, 
    company_id: 1, 
    type: "Person", 
    created_at: Fri, 04 Aug 2017 10:57:41 UTC +00:00, 
    updated_at: Fri, 04 Aug 2017 10:57:41 UTC +00:00>, 
#<Person:0x007fd55d796208 
    id: 3, 
    company_id: nil, 
    type: "Person", 
    created_at: Fri, 04 Aug 2017 10:57:41 UTC +00:00, 
    updated_at: Fri, 04 Aug 2017 10:57:41 UTC +00:00>] 

> Person.last.company 
    Person Load (0.2ms) SELECT "recipients".* FROM "recipients" WHERE "recipients"."type" IN ('Person') ORDER BY "recipients"."id" DESC LIMIT ? [["LIMIT", 1]] 
=> nil 

> Person.first.company 
    Person Load (0.2ms) SELECT "recipients".* FROM "recipients" WHERE "recipients"."type" IN ('Person') ORDER BY "recipients"."id" ASC LIMIT ? [["LIMIT", 1]] 
    Company Load (0.2ms) SELECT "recipients".* FROM "recipients" WHERE "recipients"."type" IN ('Company') AND "recipients"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] 
=> #<Company id: 1, company_id: nil, type: "Company", created_at: "2017-08-04 10:57:41", updated_at: "2017-08-04 10:57:41"> 
+0

這幾乎是我想到的。感謝澄清這一點。 – Tintin81

+0

@ Tintin81太棒了!還有什麼你需要的?或者你能接受答案嗎? –

1
class Recipient < ActiveRecord::Base 
end 

class Company < Recipient 
    has_many :people, class_name: "Recipient", foreign_key: 'parent_id' 
end 

class Person < Recipient 
    belongs_to :company, class_name: "Recipient", foreign_key: 'parent_id' 
end 

只需將parent_id添加到收件人遷移。 這就是它簡單和快速,你得到你想要的一個模型兩個STI和has_manybelongs_to之間companyperson

+0

非常感謝。是'class_name:「收件人」'必須得到這個工作? – Tintin81

+0

@ Tintin81不,你喜歡使用它更多的信息更好:) –

+0

謝謝,我冒昧地將弗雷德裏克的答案標記爲正確的答案,因爲他更詳細地介紹了一些細節,但我可能會標記你的。你們在這裏幫了我很多。 – Tintin81