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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了检索ActiveRecord / Rails中没有关系的对象相关的知识,希望对你有一定的参考价值。

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

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

所以我可以在代码中执行以下操作:

User.all.select {|user| not user.is_staff? }

这似乎工作,但我想在数据库中有这个逻辑,并且我在尝试以这种方式排序时出于某种原因使用Heroku生成错误(dev with 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

我因某些原因得到的错误是:

ArgumentError: comparison of User with User failed

无论如何,如果我想获得所有员工,那看起来很简单:

User.joins(:staff)

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

User.not_joins(:staff)

而且我真的需要用户不是员工或管理员:

User.not_joins(:staff, :admin)
答案

要使所有用户与Staff无关,您可以使用以下内容:

User.includes(:staff).where(staff: { id: nil }) 

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

Staff.includes(:user).where(users: { id: nil })
                   ^            ^

要知道的事情:在includes(和preloadjoins)方法中,你必须使用模型中定义的关系名称(belongs_tohas_one:singularize,has_many:pluralize),但是在where子句中你必须使用复数版本关系(实际上,表的名称)。

另一答案

你有3个解决方案:

  • 做一些没有优化和肮脏的事情: User.where('id NOT IN(?)', Staff.select(:user_id).all.map(&:user_id).uniq).all

或者像Mr.Yoshiji说的那样

    User.includes(:staff).where(:staff => {:id => nil})
  • 为您的表用户添加一个字段,以了解您的用户是否有员工,因此您必须在为用户创建员工后将此字段设置为true,但您可以轻松地让所有用户 User.where(:have_staff => false).all
  • 或者你反转你的关系,并说工作人员has_one用户和用户belongs_to工作人员和获得你做的所有用户 User.where(:staff_id => nil).all

以上是关于检索ActiveRecord / Rails中没有关系的对象的主要内容,如果未能解决你的问题,请参考以下文章

Rails ActiveRecord - 获取与锁定的belongs_to关联

Rails ActiveRecord,其中datetime不起作用

有没有办法在后续 Rails 3 ActiveRecord 迁移中删除 id 列?

没有Rails的ActiveRecord

ruby 没有Rails的Activerecord

ruby 没有Rails的Activerecord