2011-12-29 36 views
1

我有我建設我的Rails應用程序對於產品的價格模型:如何將ActiveRecord屬性重新映射爲外鍵,且中斷最少?

class Price < ActiveRecord::Base 
    validates_presence_of :country_code, :product, :amount 
    validates_uniqueness_of :product, :scope => [:country_code] 
end 

適當地,DB模式如下:

create_table :prices do |t| 
    t.string :country_code 
    t.integer :product_id 
    t.integer :amount 
end 

的複雜之處在於,在時刻,產品不是一個實際的ActiveRecord模型 - 它是一個包裹着單個ID屬性(item_code)的Struct,包含很多常量和輔助方法。未來Sprint計劃將其重構爲適當的數據庫,但現在,我們的許多應用程序代碼都使用Product,就好像它已經來自數據庫一樣,理想情況下,我希望隔離多次更改產品成爲適合DB中直接關係的模型的適當表格。

然後,問題是在底層數據庫中沒有實際的其他表時,乾淨地處理模型中的外鍵關係。爲了解決它在邏輯上,我已經添加了下面的驗證,以價格:

validates_inclusion_of :product, :in => Product.all 

哪裏Product.all是模擬這些對象從一個表來而不實際ActiveRecord類的方法。

所有這一切導致的問題,據我瞭解,因爲沒有產品表,ActiveRecord不會創建產品訪問器(而是直接使用product_id)。但是,如果我依賴:product_id,那麼一旦Product成爲實際的ActiveRecord類,我就難以遷移。

是否有一種簡單的方法可以將product屬性「別名」爲:product_id字段,以便代碼在產品(甚至是價格模型)中被隔離,以便爲了所有意圖和目的, :產品會自動映射,就好像數據庫表中存在關係一樣?顯然,理想的解決方案是某種方法或別名指令,它們可能會在將來的某個日期被刪除,並且突然間所有操作都會像product_id一直指向產品表一樣。

回答

0

如果您只是想僞造字段,就好像在Price模型中設置has_one關係一樣,您可以在Price模型中自己定義方法。由於您沒有舉例說明如何從Product Struct中進行選擇,因此如果您試圖爲ActiveModel重新實現它,則下面是一個代碼示例。

def product 
    if self.product_id 
     if [email protected] or @product.id != self.product_id 
      @product = Product.find(self.product_id) 
     else 
      @product 
     end 
    end 
end 

def product=(product) 
    @product = product 
    self.product_id = product._id 
end 

這將複製has_one關係,在那裏你可以通過productproduct_id設置它改變它,如果它改變它只會查找產品一次,然後再次。

+0

這確實奏效,但我還必須做更多的事情。也就是說,validates_uniqueness_of調用必須從product更改爲product_id,並且ActiveRecord find調用必須使用product_id而不是product(例如find_by_product_id_and_country_code)。除此之外,這是我需要的關鍵。 – Jon 2011-12-30 07:39:14