我希望能够比较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
编辑:我已经添加了我自己的答案作为下面这个问题的解决方案
答案 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)