2009-08-03 52 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了解详情。