Rails自连接条件仅适用于父级

时间:2018-05-13 21:52:40

标签: ruby-on-rails activerecord

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 (假设员工有这样的布尔字段) true ,是经理,可以显示下属

如果我只是将上面改为

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 个答案:

答案 0 :(得分:4)

为什么不创建一个类方法[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

或者,考虑到您的业务需求&#39; (非常奇怪,业务部门对此级别的实现细节有要求),您如何抢占subordinates指令提供的has_many方法呢?

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 Purists之一,他们喜欢指出Ruby中没有类方法。但是,我完全没问题,通常使用术语类方法 ,只要所有各方都完全理解这是一种口语用法。换句话说,如果你知道没有类方法和术语&#34;类方法&#34;对于作为Class&#34;的实例的对象的单例类的&#34;实例方法,它只是简短的,那么就没有问题。但除此之外,我只看到它阻碍了理解。

让所有各方充分理解, class method 这个术语在上面的口语中使用。