查找rails 3中没有关联记录的记录

Sha*_*moe 13 scope ruby-on-rails

class Person < ActiveRecord::Base
  has_many :pets

  scope :with_dog, join(:pets).where("pets.type = 'Dog'")
  scope :without_pets ???????????????????????????????????
end

class Pet < ActiveRecord::Base
  belongs_to :people
end
Run Code Online (Sandbox Code Playgroud)

我想在Person模型中添加一个范围,返回没有宠物的人.有任何想法吗?我觉得这很明显,但此刻它正在逃避我.

Sam*_*roa 22

scope :without_pets, lambda { includes(:pets).where('pets.id' => nil) }
Run Code Online (Sandbox Code Playgroud)

  • 无论目的如何,这都有效.比接受的答案更少的手写sql =我认为它更好. (2认同)

Mar*_*ing 9

尝试这样的事情:

Person.joins('left outer join pets on persons.id=pets.person_id').
       select('persons.*,pets.id').
       where('pets.id is null')
Run Code Online (Sandbox Code Playgroud)

我没有测试它,但它应该工作.

我们的想法是,我们正在执行左外连接,因此对于没有宠物的每个人来说,宠物字段将为空.您可能需要:readonly => false在连接中包含,因为ActiveRecord在join()传递字符串时返回只读对象.


Mik*_* A. 5

Mark Westling的回答是正确的.外连接是正确的方法.内部联接(如果您传递联接的名称/符号而不是您自己的SQL,则联接方法生成的内容)将不起作用,因为它不包括没有宠物的人.

这里写的是一个范围:

scope :without_pets, joins("left outer join pets on pets.person_id = persons.id").where("pets.id is null")
Run Code Online (Sandbox Code Playgroud)

(如果这不起作用,尝试用'人'替换'人' - 我不确定你的表名是什么.)