2011-03-07 58 views
8

我想创建一个延迟加载的属性,返回模型上的集合,我该如何做到这一点?如何在Ruby中为模型创建惰性加载属性?

我不想为此创建关联。

所以我希望它返回一个集合,如果集合尚未初始化,然后命中数据库,返回行,然后初始化它。

如果它运行一次,则不需要再次运行它,因为下一个页面请求会启动。

+0

你为什么要这样做?这正是一个协会的目标。 – tadman 2011-03-07 16:39:44

+0

@tadman b/c它不适合我的工作,请参阅:http://stackoverflow.com/questions/5215836/could-i-add-an-association-based-on-another-association – Blankman 2011-03-07 16:59:22

回答

19

添加的实例属性(如@my_attribute

,然后定义

def my_attribute 
    @my_attribute ||= initialize_my_attribute 
end 

(注:initialize_my_attribute是一个函数/方法,你已经实现,这将加载所需的值)

工作原理:该属性以nil的值开始(我们还没有分配任何东西)。对象实例无法直接访问它,因为我们尚未定义属性访问器。相反,我们有一个名称与属性完全相同的方法,因此当您调用my_object.my_attribute时,它看起来就像在实际调用对象实例的方法时正在访问该属性。

该方法会发生什么?该||=短手相当于

@my_attribute = (@my_attribute || initialize_my_attribute) 

所以,如果@my_attribute已经有值,则返回该值。否则,@my_attribute会获取分配的值(然后返回)。换句话说:首次访问该值时(仅在第一次),该值将被加载到@my_attribute中。

瞧!延迟加载。

+0

谢谢彻底回应+1 – jcollum 2012-01-30 23:11:20

+0

实际上,'|| ='是'@my_attribute =(@my_attribute || initialize_my_attribute)'的快捷方式,它与您的关于falsy non-nil值的示例略有不同。 – AmShaegar 2015-03-12 11:31:57

+0

好点:我编辑我的回复这个效果。 – 2015-03-13 15:52:59

0

默认情况下,相关属性是延迟加载的。检查你的日志,看看只有在访问属性时才会对数据库进行查询。

我也遇到过这个问题。在我实现了我自制的懒惰加载函数之后,我意识到它们毫无意义。通过添加如上所述的懒加载器,您可以将lazy-loader添加到内部lazy-loader,这会使性能变慢,而不会增加任何值。