所以,我的课程包含多个课程。在课程页面上,我显示所有课程和一个图标,以指示用户是否已完成课程。我注意到(逻辑上)Rails正在查询每节课的完成表。
这是我的模型方法,用于检查用户是否已完成课程:
class Lesson < ActiveRecord::Base
def is_completed_by? current_user
return true if (current_user && self.completions.find_by(user: current_user))
return false
end
end
所以我认为最好在实例变量中存储用户的所有完成列表,并检查该集合中是否存在记录。我尝试过类似的事情:
def is_completed_by? current_user
@completed_list ||= Completion.where(user: current_user)
return true if (current_user && self.in?(@completed_list))
return false
end
但这仍会触发多个查询。我在某个地方犯了错误吗?
答案 0 :(得分:1)
is_completed_by?
是Lesson
类的实例方法。 @completed_list
是一个实例变量。
因此,每次在循环中调用方法时,都会在每个lesson
实例上触发新查询。
尝试将整个检查方法或至少完成的列表放在&#34; persistent&#34; (在循环范围内)对象,例如当前用户。
class User
def completed_list
@completed_list ||= Completion.where(user: self)
end
end
class Lesson
def is_completed_by? current_user
current_user && self.in?(current_user.completed_list))
end
end
答案 1 :(得分:0)
@completed_list
是ActiveRecord::Relation
,这就是每次使用时调用查询的原因。尝试将其转换为数组:
@completed_list ||= Completion.where(user: current_user).to_a
但是我认为这不是一个好的解决方案,更好的是使用一些缓存方式,例如:
def is_completed_by? current_user
Rails.cache.fetch("#{cache_key}/is_completed_by") do
return true if (current_user && self.completions.find_by(user: current_user))
return false
end
end
如果已添加/更新完成,则应记得在Lesson对象上使用touch
方法。