2

假設我有5張桌子。 ActiveRecord可以處理這個問題嗎?你將如何設置它?如何模擬這種多繼承關係瓦特/ Ruby的ActiveRecord的?

層次結構:

Account (Abstract) 
    CorporateCustomer (Abstract) 
    PrivateCustomer 
    PublicCustomer 
    GovernmentCustomer 

編輯:在NHibernate和ActiveRecord的城堡,使此方案所需的方法被稱爲「聯合子類」。

+0

如果帳戶/ CoroprateCustomer是一個抽象類,一個很好的討論,它真的需要一個表? – Swanand 2009-06-19 15:50:52

+0

我相信如此。我改變了實體名稱,以使它們不具有域特定性(如果以下內容有點人爲的話,請原諒我)。 CorporateCustomers有1:M的關係,政府客戶不。例如,公司客戶可以有許多財務報表。因爲我不想要GovCustomers有這種關係,所以我把表格分開,所以我的FinancialStatement表格可以在CorpCustomers上FK。 – 2009-06-19 16:04:06

+0

此外,所有3個實體(私人,公共和政府)共享相同的PK ID空間。因此私人和政府客戶不可能擁有1的PK。賬戶表確保。在這種情況下你會認爲這些表格是需要的嗎? – 2009-06-19 16:04:47

回答

0

搜索ActiveRecord的Single Table Inheritance功能。 不幸的是,我無法在網上找到更詳細的參考鏈接。我讀過的最詳細的解釋是來自「The Rails Way」一書。

0

這是一個辦法(最簡單的),這樣做的:

class Account < ActiveRecord::Base 
    self.abstract_class = true 
    has_many :corporate_customers 
    has_many :government_customers 
end 


class CorporateCustomer < ActiveRecord::Base 
    self.abstract_class = true 
    belongs_to :account 
    has_many :private_customers 
    has_many :public_customers 
end 


class PrivateCustomer < ActiveRecord::Base 
    belongs_to :corporate_customer 
end 

class PublicCustomer < ActiveRecord::Base 
    belongs_to :corporate_customer 
end 

class GovernmentCustomer < ActiveRecord::Base 
    belongs_to :account 
end 

注:抽象模型是不能有物體(不能被實例化)的模型,因此它們沒有關聯的表以及。如果你想擁有表格,那麼我就不明白爲什麼需要抽象類。

0

假設大部分數據是共享的,你只需要一個表:帳戶。這隻會工作,假設帳戶有一個字符串類型列。

class Account < ActiveRecord::Base 
    self.abstract_class = true 
end 

class CorporateCustomer < Account 
    self.abstract_class = true 
    has_many financial_statements 
end 

class PrivateCustomer < CorporateCustomer 
end 

class PublicCustomer < CorporateCustomer 
end 

class GovernmentCustomer < Account 
end 

Google for Rails STI,特別是Rails STI摘要,以獲取更多有用的信息。

4

你可以嘗試大意如下的東西。

class Account < ActiveRecord::Base 
    belongs_to :corp_or_gov_customer, :polymorphic => true 

    def account_id 
    self.id 
    end 
end 

class GovernmentCustomer < ActiveRecord::Base 
    has_one :account, :as => :corp_or_gov_customer, :dependent => :destroy 

    def method_missing(symbol, *args) 
    self.account.send(symbol, *args) 
    end 
end 

class CorporateCustomer < ActiveRecord::Base 
    has_one :account, :as => :corp_or_gov_customer, :dependent => :destroy 
    belongs_to :priv_or_pub_customer, :polymorphic => true 

    def method_missing(symbol, *args) 
    self.account.send(symbol, *args) 
    end 
end 

class PrivateCustomer < ActiveRecord::Base 
    has_one :corporate_customer, :as => :priv_or_pub_customer, :dependent => :destroy 

    def method_missing(symbol, *args) 
    self.corporate_customer.send(symbol, *args) 
    end 
end 

class PublicCustomer < ActiveRecord::Base 
    has_one :corporate_customer, :as => :priv_or_pub_customer, :dependent => :destroy 

    def method_missing(symbol, *args) 
    self.corporate_customer.send(symbol, *args) 
    end 
end 

我還沒有測試過這個代碼(甚至沒有檢查過它的語法)。相反,它僅僅是爲了向你指出多態關係的方向。

重載method_missing的調用嵌套對象保存如下

my_public_customer.corporate_customer.account.some_attribute 

編寫代碼,而不是你可以隨便寫

my_public_customer.some_attribute 

在迴應評論:

的問題是,像「是一個」,「有很多」和「屬於」的概念都是通過外鍵實現的關係模型中的關係。繼承的概念與RDB系統完全不同。這些關係的語義必須通過您選擇的ORM技術映射到關係模型。

但Rails的ActiveRecord庫未實現‘is_a’作爲模型之間的關係。

有幾種方法你的類層次結構RDB中的建模。

所有帳戶但具有冗餘屬性的單個表 - 只需在表中添加「類型」列即可支持ActiveRecord。然後創建的類層次結構是這樣的:

class Account < ActiveRecord::Base 
class GovernmentCustomer < Account 
class CorporateCustomer < Account 
class PublicCustomer < CorporateCustomer 
class PrivateCustomer < CorporateCustomer 

然後,如果你打電話PrivateCustomer.new類型字段將自動設置爲「PrivateCustomer」,當你調用Account.find返回的對象將是一個正確的類。

這是我推薦的方法,因爲它是迄今爲止最簡單的方法來做你想做的事。

每個具體類的一個表 - 據我所知在ActiveRecord中沒有爲此提供映射。這種方法的主要問題是,要獲得所有帳戶的列表,您必須加入三個表。需要的是某種主索引,這導致了下一個模型。

每個類的一張表 - 您可以將表示抽象類的表視爲一種統一索引,或存儲在具體類的表中的對象的目錄。通過這種方式思考它,你正在將is_a關係改變爲has_a關係,例如對象has_a index_entry和index_entry屬於對象。這可以通過使用多態關係的ActiveRecord進行映射。

出現這個問題的書中"Agile Web Development with Rails"(在第2版起341頁)