Rails: поиск глубоко вложенной связи с предложением where

У меня есть две модели, соединенные с has_many: через отношение:

class Publication < ActiveRecord::Base
  has_many :publication_contributors
  has_many :contributors, :through => :publication_contributors
end

class Contributor < ActiveRecord::Base
  has_many :publication_contributors
  has_many :publications, :through => :publication_contributors
end

class PublicationContributor < ActiveRecord::Base
  belongs_to :publication
  belongs_to :contributor
end

(Что-то необычное и важное в моей модели PublicationContributor заключается в том, что у него есть не только пара идентификаторов базы данных, но и атрибут string, называемый contributor_type. Эта строка может содержать такие роли, как "Автор" или "Переводчик" или "Переводчик", Издатель ". Я не верю, что в этом проблема, но решение должно все еще учитывать это.)

Я хочу найти публикацию с конкретными вкладчиками:

Publication
  .joins(:publication_contributors =>  :contributor)
  .where(:publication_contributors => 
            {:contributor_type => "Author", 
             :contributor => {:name => params[:authors]}})

Все работает нормально, пока не дойду до вложенного: contributor, после чего SQL sputters:

Mysql2::Error: Unknown column 'publication_contributors.contributor' in 'where clause'

Вместо поиска publish_contributors.contributor_id он ищет публикацию_contributors.contributor, которой не существует. Я что-то делаю в своем коде? Я не могу найти никаких других примеров предложения where с такими глубоко вложенными ассоциациями. Возможно, это даже не возможно?

UPDATE:

Сгенерированный SQL

←[1m←[35mPublication Load (0.0ms)←[0m  SELECT `publications`.* FROM `publicati
ons` INNER JOIN `publication_contributors` ON `publication_contributors`.`public
ation_id` = `publications`.`id` INNER JOIN `contributors` ON `contributors`.`id`
 = `publication_contributors`.`contributor_id` WHERE `publication_contributors`.
`contributor_type` = 'Author' AND `publication_contributors`.`contributor` = '--
-\n:name:\n- Marilynne Robinson\n' LIMIT 1

Кроме того, у меня есть эта ассоциация в моей модели публикаций:

has_many :authors, :through => :publication_contributors, :source => :contributor, :conditions => {:publication_contributors => {:contributor_type => "Author"}}

Я думал, что могу это сделать:

Publication.joins(:authors).where(:authors => {:name => params[:authors]})

Но это вызывает ошибку:

Mysql2::Error: Unknown column 'authors.name' in 'where clause'

Ответы

Ответ 1

попытайтесь изменить предложение where:

Publication
  .joins( :publication_contributors => :contributor )
  .where( :publication_contributors => {:contributor_type => "Author"}, 
          :contributors             => {:name => params[:authors]} ) 

ActiveRecord api здесь не очень последователен: аргументы для where не работают точно так же, как и для joins. Это связано с тем, что аргументы для joins не отражают базовый SQL, тогда как аргументы для where делают.

where принимает хэш, ключи которого имена таблиц, а значения - хеши (которые сами имеют имена столбцов в качестве ключей). Он просто предотвращает двусмысленность при указании столбца с таким же именем в двух таблицах.

Это также объясняет, почему возникает ваша вторая проблема: отношения authors не существует.