Rails - has_one 关系:关联和非关联对象的范围
Posted
技术标签:
【中文标题】Rails - has_one 关系:关联和非关联对象的范围【英文标题】:Rails - has_one relationship : scopes for associated and non-associated objects 【发布时间】:2011-04-19 23:39:26 【问题描述】:我有这样的关系:一个用户可以有零条或一条狗,但一条狗必须属于某人。
# dog.rb
class Dog < ActiveRecord::Base
belongs_to :user
end
# user.rb
class User < ActiveRecord::Base
has_one :dog
end
我想定义以下范围:
User.with_a_dog
User.without_a_dog
我可以在第一种情况下这样做,因为在 rails 中默认情况下连接是 INNER JOIN :
scope :with_a_dog, :joins(:dog)
1/ 第一个范围的解决方案是否足够好?
2/ 你会为第二个做什么?
3/(有点相关)有更好的方法吗? :
# user.rb
def has_a_dog?
!self.dog.nil?
end
感谢您的帮助!
【问题讨论】:
应该是范围 :with_a_dog, joins(:dog) 没有“:” 【参考方案1】:只是想添加这个以防有人发现它有用:
user.rb
class User < ActiveRecord::Base
has_one :dog
# To get records with a dog we just need to do a join.
# AR will do an inner join, so only return records with dogs
scope :with_a_dog, -> joins(:dog)
# To get records without a dog, we can do a left outer join, and then only
# select records without a dog (the dog id will be blank).
# The merge with the Dog query ensures that the id column is correctly
# scoped to the dogs table
scope :without_a_dog, ->
includes(:dog).merge( Dog.where(:id => nil) )
end
狗.rb
class Dog < ActiveRecord::Base
belongs_to :user
end
【讨论】:
【参考方案2】:对于问题 2,我认为以下应该可行:
scope :without_a_dog include(:dog), where('dogs.id is null')
其中 include 应该做一个左连接,这意味着在没有狗关系的地方加入用户, dogs.id 列应该为空。
【讨论】:
无法让它在 Rails 3.2 上运行,但这成功了:scope :without_profile, lambda includes(:user_profile).where('user_profiles.id is null')
【参考方案3】:
user.rb
scope :without_a_dog, ->
includes(:dog).select |user| user.dog.nil?
【讨论】:
以上是关于Rails - has_one 关系:关联和非关联对象的范围的主要内容,如果未能解决你的问题,请参考以下文章
Rails:在 rails 中使用带有 has_one 关联的 build
rails wicked gem has_one 关联和嵌套形式
Rails ActiveRecord 关联“has_many,每个都有 has_one”