2009-08-03 55 views
0

我有類似以下的類:第二十二條軍規:Rails的數據庫遷移不運行時類常量使數據庫調用

class FruitKinds < ActiveRecord::Base 
    Apple = FruitKinds.find(:all).find { |fk| 
    fk.fruit_name == :apple.to_s 
    } 

    # ... other fruits 

    # no methods 
end 

蘋果等水果的具體通常用作默認值在其他地方我應用程序,所以我想用一種方便的方式以可枚舉的,靜態的方式來引用它們。

但是,有一個問題。有一個數據庫遷移來創建FruitKinds表,並使用Apple之類的特殊Fruits進行填充。當數據庫遷移運行初始化FruitKinds時,rake無法啓動,因爲它首先加載FruitKinds,然後調用數據庫,這當然會失敗,因爲FruitKinds表尚不存在。

解決方法是在遷移運行時將FruitKinds :: *字段註釋掉,但這太可怕了。什麼是最好的方法來做到這一點?

回答

1

這是一個很常見的問題,我現在認爲在類定義級別的任何數據庫訪問都是反模式。另一種方法是讓它成爲一個懶惰的屬性。最簡單的方法是簡單地將其設置爲類級方法而不是常量。請注意,您可以在Ruby的資本化的方法,這樣可以使它看起來像一個恆定的,如果你想:

class FruitKinds < ActiveRecord::Base 
    def self.Apple 
    @apple ||= FruitKinds.find(:all).find { |fk| 
     fk.fruit_name == :apple.to_s 
    } 
    end 

    # ... other fruits 

    # no methods 
end 

或者,如果你想獲得看上你可以使用const_missing動態創建不變的第一次被訪問。

作爲一個方面說明,這是對可能的最沒有效率的方式,通過名稱來查找記錄;-)

+0

難道你不能寫自我。蘋果,使它最多擊中數據庫一次?您可以將該值保存到某個字段並具有attr_accessor。 – 2009-08-03 21:33:11

0

正如Avdi提到的,​​你要被加載的類時要避免與數據庫交互。如果你想在本地內存中緩存數據庫記錄,我建議使用在Rails 2.2中添加的Memoization功能。 See my post here瞭解詳情。