Rails:通过另一个外键过滤has_many关系

时间:2011-07-29 14:18:22

标签: ruby-on-rails ruby ruby-on-rails-3

我想知道人们是否可以通过其他外键来分享他们首选的方法来过滤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每次都去数据库。

在某种程度上,这是一个性能问题,这意味着没有一个通用的答案,你需要在生产中测试代码以找到正确的方法。但在您的代码投入生产之前,您倾向于选择哪种方法?还是别的什么?

2 个答案:

答案 0 :(得分:2)

我个人更喜欢范围(方法4)或类方法。

我相信在正常情况下,如果使用链式范围,则方法4和方法1应生成相同的SQL语句,如:

project.employees.from_department(department_id)

您可以尝试在控制台中添加.to_sql调用,以查看生成的实际sql。

对于性能(sql)分析,您可以使用query-reviewerrack-bug等工具,这些工具非常方便实用。

答案 1 :(得分:1)

project.employees.find_by_department_id(department)

(与#3基本相同)