减少检查用户是否已完成课程的查询

时间:2015-12-07 16:36:02

标签: ruby-on-rails

所以,我的课程包含多个课程。在课程页面上,我显示所有课程和一个图标,以指示用户是否已完成课程。我注意到(逻辑上)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

但这仍会触发多个查询。我在某个地方犯了错误吗?

2 个答案:

答案 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_listActiveRecord::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方法。