【问题标题】:Rails active record query: Find records on one side of a has_many :through that haven't been used with a particular record on the other sideRails 活动记录查询:在 has_many 的一侧查找记录:通过另一侧的特定记录未使用过的记录
【发布时间】:2012-02-28 04:35:31
【问题描述】:

我有一个 has_many :through 像这样设置的关系

class Situation < ActiveRecord::Base
  has_many :notifications
  has_many :notiftypes, through: :notifications
end

class Notification < ActiveRecord::Base
  belongs_to :situation
  belongs_to :notiftype
end

class Notiftype < ActiveRecord::Base
  has_many :notifications
  has_many :situations, through: :notifications
end

所以,一个Situation有很多Notifications,可以有很多类型(Notiftype)。

我的问题是尝试查询尚未为特定situation 设置的notiftypes

Want to find records with no associated records in Rails 3

那个问题的答案让我很接近,但只是为了找到根本没有设置的 Notiftypes。

如果这是标准 :situation has_many :notiftypes 我可以像这样进行左外连接

myquery = Notiftype.joins('LEFT OUTER JOIN situations ON situations.notiftype_id = notiftype.id').where('notiftype_id IS NULL')

但我真的不确定如何使用它们之间的中间表来执行此操作。

我一直在尝试连续加入,但它不起作用。我不知道如何加入这两个分开的表。

谁能解释查询数据库的正确方法?我现在正在使用 SQLite、Rails 3.1、Ruby 1.9.2,但将来可能会使用 Postgresql。

【问题讨论】:

    标签: ruby-on-rails activerecord has-many-through


    【解决方案1】:

    试试这个:

    class Situation < ActiveRecord::Base
      # ...
      has_many :notiftypes, through: :notifications do
    
        def missing(reload=false)
          @missing_notiftypes = nil if reload
          @missing_notiftypes ||= proxy_owner.notiftype_ids.empty? ?
            Notiftype.all : 
            Notiftype.where("id NOT IN (?)", proxy_owner.notiftype_ids)
        end
      end
    end
    

    现在获取缺少的 Notiftype

    situation.notiftypes.missing
    

    如果您想进一步优化它以使用一个 SQL 而不是两个,您可以执行以下操作:

    class Situation < ActiveRecord::Base
      # ...
      has_many :notiftypes, through: :notifications do
    
        def missing(reload=false)
          @missing_notiftypes = nil if reload
          @missing_notiftypes ||= Notiftype.joins("
              LEFT OUTER JOIN (#{proxy_owner.notiftypes.to_sql}) A
              ON A.id = notiftypes.id").
            where("A.id IS NULL")
        end
      end
    end
    

    您可以通过以下方式访问缺少的通知类型:

    situation.notiftypes.missing
    

    【讨论】:

    • 用一个SQL解决方案更新了答案,看看吧。
    • 有效!我将 proxy_owner 替换为 stackoverflow.com/questions/7001810/…
    • 对不起...我早点进入。我根据这个线程stackoverflow.com/questions/7001810/…用proxy_association.owner替换了proxy_owner 有必要吗? proxy_owner 方法没有出现任何错误,而且它们都可以正常工作。
    • 我的代码基于 Rails 2.3.x,看起来proxy_owner 已被弃用。
    • 明白了。正如我所说,proxy_association.owner 在 3.1.1 上为我工作
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-01
    相关资源
    最近更新 更多