比较不同ActiveRecords上的关联,而无需从DB中获取

时间:2015-04-25 21:41:32

标签: ruby-on-rails ruby-on-rails-4 activerecord

我希望能够比较ActiveRecords上的相关记录,而无需实际从数据库中获取。以下将进行比较,但在进行比较时命中数据库

employee1 = Employee.find_by(name: 'Alice')
  DEBUG   Employee Load (92.0ms)  SELECT "employees".* FROM "employees" WHERE "employees"."name" = 'Alice' LIMIT 1

employee2 = Employee.find_by(name: 'Bob')
  DEBUG   Employee Load (92.0ms)  SELECT "employees".* FROM "employees" WHERE "employees"."name" = 'Bob' LIMIT 1

employee1.manager == employee2.manager
  DEBUG   Employee Load (697.9ms)  SELECT "employees".* FROM "employees" WHERE "employees"."id" = $1 ORDER BY "employees"."id" ASC LIMIT 1  [["id", 53]]
  DEBUG   Employee Load (504.1ms)  SELECT "employees".* FROM "employees" WHERE "employees"."id" = $1 ORDER BY "employees"."id" ASC LIMIT 1  [["id", 53]]
 => true

我可以直接比较外来列的值,但这不太习惯,以后很难重构:

employee1.manager_id == employee2.manager_id
 => true

编辑:我已经添加了我自己的答案作为下面这个问题的解决方案

2 个答案:

答案 0 :(得分:0)

如果您知道在操作期间需要/使用Manager Employee,您可以确保在加载员工时加载该对象,这将阻止回到数据库:

employee1 = Employee.includes(:manager).find_by(name: 'Alice')
employee2 = Employee.includes(:manager).find_by(name: 'Bob')
employee1.manager == employee2.manager
 => true # database hit not needed...

那或只是比较ID,但在Employee上创建一个帮助方法,如

class Employee
  def same_manager?(other_employee)
    other_employee.manager_id == self.manager_id
  end
end

至少就是这样,它给出了一个名称,其中的操作在上下文中是有意义的。

答案 1 :(得分:0)

我暂时会发布自己的答案。我已经修补了Active Record以包含一个新方法compare_association,它允许您在不命中数据库的情况下比较不同ActiveRecords上的异物。

module ActiveRecord
  class Base
    def compare_association(association_name, record)
      association = self.class.reflect_on_association(association_name)
      foreign_key = association.foreign_key

      return self.read_attribute(foreign_key) == record.read_attribute(foreign_key)
    end
  end
end

示例:

# Compare the 'manager' association of `employee1` and `employee2`
# Equivalent to `employee1.manager_id == employee2.manager_id` but without
# referencing the DB columns by name.
employee1.compare_association(:manager, employee2)