考虑一下:
class Post < ActiveRecord::Base
has_many :comments
def last_comment
comments.last
end
end
railsconsole> p = Post.last
Post Load (0.2ms) SELECT `posts`.* FROM `posts` WHERE ORDER BY `posts`.`id` DESC LIMIT 1
railsconsole> p.last_message
Post Load (0.4ms) SELECT `comments`.* FROM `comments` WHERE `messages`.`post_id` = 14
railsconsole> p.last_message
Post Load (0.4ms) SELECT `comments`.* FROM `comments` WHERE `messages`.`post_id` = 14
您会认为此处只应发生2个查询:初始查找,然后加载关联。应缓存对该关联的后续调用。但是,他们不是。永远不会加载和缓存该关联,因为Rails正在尝试智能并且只加载最后一条记录。由于Rails没有跟踪最后一条记录(或关联的第一个或任何其他自定义查询),它只是每次都返回答案。
但是,如果要缓存关联怎么办?我搜索了SO并找不到直接答案。
答案 0 :(得分:5)
当您在ActiveRecord实例上调用关联时,您将返回一个代理对象,如果是has_many对象,则会获得CollectionProxy。
奇怪的是,您可以在集合代理上调用#load,但这不会加载关联缓存。
隐藏在Rails文档中:http://api.rubyonrails.org/classes/ActiveRecord/Associations/CollectionProxy.html#method-i-load_target
#load_target
|
class Post < ActiveRecord::Base
has_many :comments
def last_comment
comments.load_target unless comments.loaded?
comments.last
end
end
希望其他人觉得这很有用。
答案 1 :(得分:2)
我会将last_comment设为关联
has_one :last_comment, -> { order 'created_at DESC' }, class_name: 'Comment'
这样你也可以包括,加入或者eager_load。