Запрос активной записи Rails: Найти записи на одной стороне has_many: через которые не использовались с определенной записью на другой стороне - PullRequest
1 голос
/ 28 февраля 2012

У меня есть has_many: через отношения, настроенные так

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

Итак, у ситуации есть много уведомлений, которые могут быть разных типов (Notiftype).

Моя проблема пытается запросить notiftypes, который не был установлен для определенного situation.

Хотите найти записи без связанных записей в Rails 3

Ответы на этот вопрос приближают меня, но только до точки нахождения типов уведомлений, которые не были установлены ВСЕ.

Если бы это был стандарт :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 в будущем.

1 Ответ

0 голосов
/ 28 февраля 2012

Попробуйте это:

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

Теперь, чтобы получить отсутствующий тип уведомления

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
...