【问题标题】:ActiveRecord: How to unscope a default_scope when using left_join?ActiveRecord:如何在使用 left_join 时取消 default_scope 的范围?
【发布时间】:2019-10-02 00:41:23
【问题描述】:

假设我有一个模型Person。这个Person 有很多Posts。帖子具有排除所有软删除条目的默认范围。软删除意味着属性deleted_at 不是nil

class Person < ActiveRecord::Base

  has_many :posts

end

class Post < ActiveRecord::Base

  belongs_to :person
  default_scope { where(:deleted_at => nil) }

end

我现在想查询至少有一个帖子的所有人,并且我还想包括软删除的帖子 - 所以我希望默认范围不适用。使用

Person.left_joins(:posts).where.not(posts: { id: nil })

在此 SQL 中仍然应用默认范围和结果:

SELECT `persons`.* FROM `persons` LEFT OUTER JOIN `posts` ON `posts`.`person_id` = `persons`.`id` AND `posts`.`deleted_at` IS NULL WHERE `posts`.`id` IS NOT NULL

解决这个问题的优雅方法是什么?

【问题讨论】:

    标签: ruby-on-rails join activerecord ruby-on-rails-5 left-join


    【解决方案1】:

    使用unscoped 方法删除所有以前的范围。

    Person.unscoped.left_join(....
    

    https://api.rubyonrails.org/classes/ActiveRecord/Scoping/Default/ClassMethods.html#method-i-unscoped

    编辑:我误解了默认范围在哪里,我认为您可以取消关联范围:

    has_many :posts, -> { unscoped }
    

    https://guides.rubyonrails.org/association_basics.html#scopes-for-has-many

    默认情况下,这应该取消关联的范围。虽然不是 100% 肯定!希望对您有所帮助。

    【讨论】:

    • 啊,不,不起作用。默认范围不在Person 上,而是在Post 上,关联。问题是unscoped 删除了所有应用的条件,包括关联。
    【解决方案2】:

    我在 Rails 5 中尝试过这种方式,它可以工作:

    has_many :posts, -> { unscope( where: : deleted_at) }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-09-16
      • 1970-01-01
      • 2014-04-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-08
      • 1970-01-01
      相关资源
      最近更新 更多