【问题标题】:Rails - has_one relationship : scopes for associated and non-associated objectsRails - has_one 关系:关联和非关联对象的范围
【发布时间】: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) 没有“:”

标签: sql ruby-on-rails activerecord


【解决方案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? }
      }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-07
      • 2016-07-01
      • 2016-07-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多