在ActiveRecord中避免db命中

时间:2012-09-28 17:24:31

标签: ruby-on-rails-3 activerecord instance-variables

当我在Rails中分配数据库查找实例变量时,为什么以后对该变量的请求也会命中数据库?这可以避免吗?

例如,我有3个模型:User,Resource,Opinion,with has_many:through on Opinion

@opinions = current_user.opinions # pulls in all of the user's opinions, which include respective resource ids
1.直接调用resource_id不会访问数据库:
@opinions.each do |opinion|
  opinion.resource_id  # does not hit the database (as expected)
end
2.执行查询确实命中了数据库(即使已经分配了变量):
@opinions.find_by_resource_id(1) # DOES hit the database

为什么#2命中数据库?有没有办法在不点击数据库的情况下执行相同的查找?

该信息已包含在@opinions变量中,因此似乎不需要进行db调用。

1 个答案:

答案 0 :(得分:0)

如果@opinions数组中不需要任何其他内容,我会将原始查询的范围仅包含resource_id

的意见
@opinions = current_user.opinions.where("resource_id = ?", resource_id)

如果您已经拥有@opinions并且只想创建一个与特定键/值匹配的新对象数组:

@opinions_with_resource_id = @opinions.select { |opinion| opinion.resource_id == 1234 }

查看this other answer以获取其他说明,或者如果您想将答案拆分为多个数组。

思想

评论您的最后一段代码

像你这样调用find_by_*的方法是动态查找程序,它使用method_missing命中数据库并查看*指定的列内部。

以前回答的剩余评论

如果此对象需要访问资源模型上的数据,请不要忘记.include()方法,这将使您不必在路上运行其他查询。

@opinions = current_user.opinions.include(:resources)

请参阅http://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations