我想知道人们是否可以通过其他外键来分享他们首选的方法来过滤has_many关系的内容。例如,假设您有三个实体:部门,员工,项目。部门有很多员工,项目有很多员工。我有一个项目,我想从一个给定的部门获得所有员工。我的代码如下所示:
# department.rb
has_many :employees
# employee.rb
belongs_to :department
belongs_to :projects
# project.rb
has_many :employees
现在我可以想出解决问题的四种方法:
方法1:类查询方法:
# anywhere.rb
Employee.where(:project_id => project, :department_id => department)
方法2:助手方法
# project.rb
def employees_from_department(department)
employees.select { |emp| emp.department == department }
end
方法3:关系上的帮助方法
# project.rb
has_many :employees do
def from_department(department)
where(:department_id => department)
# Could also be all.select { |emp| emp.department == deparment }
end
end
方法4:范围
# employee.rb
scope :from_department, lambda { |department|
where(:department_id => department)
}
# anywhere.rb
project.employees.from_department(department)
我几乎总是选择方法#4,因为它是最可重复使用的。我可以将该范围应用于任何返回Employees的查询。我可以将它与其他作用域组合,设置一个排序等。另外,使用作用域意味着我所有的只读,查询样式的代码都被命名为相当一致并在顶部组织,所以我的方法更少。范围是我最喜欢的Rails功能之一。但是我发现自己一直都在编写它们,所以我几乎得到了一个参数化的范围来匹配每一个:belongs_to。这是正确的方法吗?此外,我似乎正在生成大量的数据库查询,所以我想知道我是否打败了Rails可能为我做的任何缓存,因为我的范围正在迫使Rails每次都去数据库。
在某种程度上,这是一个性能问题,这意味着没有一个通用的答案,你需要在生产中测试代码以找到正确的方法。但在您的代码投入生产之前,您倾向于选择哪种方法?还是别的什么?
答案 0 :(得分:2)
我个人更喜欢范围(方法4)或类方法。
我相信在正常情况下,如果使用链式范围,则方法4和方法1应生成相同的SQL语句,如:
project.employees.from_department(department_id)
您可以尝试在控制台中添加.to_sql调用,以查看生成的实际sql。
对于性能(sql)分析,您可以使用query-reviewer或rack-bug等工具,这些工具非常方便实用。
答案 1 :(得分:1)
project.employees.find_by_department_id(department)
(与#3基本相同)