【发布时间】:2020-03-26 10:39:26
【问题描述】:
假设我在 Rails 中有以下模型。
class Post < ApplicationRecord
belongs_to :user
end
class User < ApplicationRecord
has_many :posts
end
当我将 Post 实例放入变量中并对其调用 user 时,以下 sql 查询运行一次,然后将结果保存/缓存。
post.user
User Load (0.9ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
#<User id: 1 ...>
post.user
#<User id: 1 ...>
etc.
但是,当我使用 user.posts 反过来时,它总是运行查询。
user.posts
Post Load (1.0ms) SELECT `posts`.* FROM `posts` WHERE `posts`.`user_id` = 1 LIMIT 11
user.posts
Post Load (1.0ms) SELECT `posts`.* FROM `posts` WHERE `posts`.`user_id` = 1 LIMIT 11
etc.
除非我将其转换为数组,否则它会被保存。
user.posts.to_a
Post Load (1.0ms) SELECT `posts`.* FROM `posts` WHERE `posts`.`user_id` = 1 LIMIT 11
user.posts
# No query here.
但是user.posts 仍然会生成一个ActiveRecord::Associations::CollectionProxy 对象,我可以在该对象上调用其他的activerecord 方法。所以这里没有真正的缺点。
为什么会这样?这似乎对 sql 优化产生了不必要的影响。我能想到的一个明显原因是,user.posts 在设置 user 之后创建帖子时会正确更新。但实际上这并没有发生太多 imo,因为变量大多是在连续运行的控制器动作中设置和重置的。现在我知道有一个缓存系统可以在服务器日志中显示 CACHE Post sql,但是当我在模型之间使用 activerecord 对象或更复杂的查询时,我不能真正依赖它。
我在这里错过了一些最佳实践吗?或者一个明显的设置可以解决这个问题?
【问题讨论】:
标签: ruby-on-rails activerecord rails-activerecord