以 http://guides.rubyonrails.org/association_basics.html#self-joins 为例,
class Employee < ApplicationRecord
has_many :subordinates, class_name: "Employee", foreign_key: "manager_id"
belongs_to :manager, class_name: "Employee"
end
如果我想应用于一个条件,比如说,只有具有is_manager的员工(假设员工有这样的布尔字段(是正确的,是经理并且可以显示下属
如果我只是将上面更改为下面
class Employee < ApplicationRecord
has_many :subordinates, -> {where is_manager: true}, class_name: "Employee", foreign_key: "manager_id"
belongs_to :manager, class_name: "Employee"
end
它不起作用,因为条件where is_manager: true
也适用于subordinates
。
FROM `employees` WHERE `employees`.`is_manager` = 1 AND (employees.manager_id = 1)
但我只想申请经理,而不是下属。
类似的东西
Employee.where(manager_id: employee.where(is_manager: true))
所以,如果我打电话
employee = Employee.find 1
employee.subordinates
首先,它将检查员工是否是经理,如果是,则返回下属;否则,返回空数组
为什么不创建一个类方法[1],as_manager
.像这样:
class Employee < ApplicationRecord
has_many :subordinates, class_name: "Employee", foreign_key: "manager_id"
belongs_to :manager, class_name: "Employee"
class << self
def as_manager
where(is_manager: true)
end
end
end
然后你应该能够做到:
Employee.as_manager.subordinates
或者,鉴于您的"业务需求"(非常奇怪的是,业务会对这种级别的实现细节有要求(,您如何抢占has_many
指令提供的subordinates
方法?
class Employee < ApplicationRecord
has_many :subordinates, class_name: "Employee", foreign_key: "manager_id"
belongs_to :manager, class_name: "Employee"
def subordinates
is_manager ? where(manager_id: id) : []
end
end
这样,您可以保留has_many
提供的所有其他方法,但获得您想要的行为subordinates
.
[1] Jörg W Mittag希望声明:
我是那些喜欢指出Ruby中没有类方法的Ruby纯粹主义者之一。不过,我完全可以口语地使用术语类方法,只要各方都完全理解它是一种口语用法。换句话说,如果您知道没有类方法这样的东西,并且术语"类方法"只是"作为
Class
实例的对象的单例类的实例方法"的缩写,那么就没有问题。但除此之外,我只看到它阻碍了理解。
让各方充分理解,上面使用的术语类方法在其口语意义上。