检索 ActiveRecord/Rails 中没有关系的对象

at.*_*at. 3 activerecord ruby-on-rails ruby-on-rails-3.2 ruby-on-rails-4 rails-activerecord

我需要从我的数据库中获取所有非员工的用户:

class User < ActiveRecord::Base
  has_one :staff
  def is_staff?
    staff != nil
  end
end
class Staff < ActiveRecord::Base
  attr_accessible :user_id
  belongs_to :user
end
Run Code Online (Sandbox Code Playgroud)

所以我可以用代码来做到这一点:

User.all.select {|user| not user.is_staff? }
Run Code Online (Sandbox Code Playgroud)

这似乎可行,但我希望在数据库中有这个逻辑,并且在尝试以这种方式排序时,由于某种原因,我在使用 Heroku 的生产中遇到错误(使用 sqlite 的开发不会给我这个错误):

NAME_SORT = ->(a, b) {
  if a.first_name == b.first_name
    a.last_name <=> b.last_name
  else
    a.first_name <=> b.first_name
  end
}
User.all.select {|user| not user.is_staff? }.sort &NAME_SORT
Run Code Online (Sandbox Code Playgroud)

由于某种原因我得到的错误是:

ArgumentError: comparison of User with User failed
Run Code Online (Sandbox Code Playgroud)

无论如何,如果我想获得所有员工用户,这似乎很简单:

User.joins(:staff)
Run Code Online (Sandbox Code Playgroud)

有没有一种简单的方法来吸引非员工的用户?也许是这样的?

User.not_joins(:staff)
Run Code Online (Sandbox Code Playgroud)

实际上我需要用户不是员工或管理员:

User.not_joins(:staff, :admin)
Run Code Online (Sandbox Code Playgroud)

MrY*_*iji 7

要获取与员工没有关系的所有用户,您可以使用以下命令:

User.includes(:staff).where(staff: { id: nil }) 
Run Code Online (Sandbox Code Playgroud)

对于以下查询“获取没有关联用户的所有员工”,它的工作方式相同:

Staff.includes(:user).where(users: { id: nil })
                   ^            ^
Run Code Online (Sandbox Code Playgroud)

需要了解的事情:includes(andpreloadjoins) 方法中,您必须使用模型中定义的关系名称(belongs_to& has_one: 单数,has_many: 复数),在 where 子句中,您必须使用关系的复数版本(实际上,表的名称)。