这个问题可能有点具体,但我认为一般的pov也很有趣。
在Rails App中,用户可以订阅其他用户。当我显示我必须检查的用户列表时,如果当前用户已订阅列表中的用户。如果他订阅了,我会显示取消订阅按钮,反之亦然。
因为整个事情取决于当前用户我不能使用急切加载。因此,当我在列表中显示20个用户时,我会在数据库上生成20个额外的点击,这在我看来是不好的做法。
我正在考虑解决这个问题的好方法。到目前为止,我提出的最佳解决方案是在登录期间加载current_user在会话中订阅的用户的ID,然后只检查每个user.id与会话中的ID。但是,当用户订阅了很多人时,这可能会导致其他问题。此外,我不确定这是否是加载所有订阅的最佳方式,即使用户在此会话期间可能永远不会查看用户列表。
我想到的最好的事情是做同样的事情,但不是在登录时,而是在加载用户列表时。
您怎么看?
答案 0 :(得分:4)
您绝对应该开始使用缓存系统。 您可以遵循至少3种方式。您也可以将它们结合起来以提高效率。
数据库缓存
创建一个关系表来保存用户和订阅者之间的ID关系,这样您就不需要动态计算它们。
模型缓存
可以缓存昂贵的查询。
def find_subscribers
Rails.cache.fetch("find_subscribers_#{current_user}") do
# run the query
end
end
查看缓存
您还可以缓存视图片段,以防止进行昂贵的细化。
您可能希望从以下开始:
修改强>
您可以优化查询。
ActiveRecord::Base.connection.execute("SELECT count(*) as c FROM subscribers_users WHERE user_id = #{other_user.id} AND subscriber_id = #{self.id}")
可以成为
counters = SubscribersUser.count(:conditions => { :subscriber_id => self.id }, :group => "user_id")
查询将返回一个Hash,其中键是user_id,值是count的结果。然后,您可以迭代哈希,而不是为视图中的任何记录运行查询。
答案 1 :(得分:2)
如果允许您使用预先加载,则没有规则可以重新加载当前用户:
user = User.find(current_user.id,:include =>:subscriber)
如果这是一个简单的has_many关系,那么这只是两个SQL语句。
现在,您可以迭代user.subscribers而不会产生另一个数据库命中。