Rails:查找与where子句的深度嵌套关联

时间:2022-09-11 17:57:37

I have two models joined with a has_many :through relationship:

我有两个模型和一个有很多的:通过关系:

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

(Something unusual and important about my PublicationContributor model is that it has more than just a pair of database ids, it also has a string attribute called contributor_type. This string could contain roles such as "Author" or "Translator" or "Publisher". I don't believe this is the problem here, but a solution must still account for it.)

(关于我的PublicationContributor模型,有一件不同寻常且重要的事情是,它不仅仅只有一对数据库id,它还有一个名为contributor_type的string属性。该字符串可以包含“Author”或“Translator”或“Publisher”等角色。我不认为这是问题所在,但必须找到解决方案。

I want to find a Publication that has specific contributors like so:

我想找一个有特定贡献者的出版物,比如:

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

Everything works fine until I get to the nested :contributor, at which point the SQL sputters:

在我进入嵌套的:contributor之前,一切都运行得很好,这时SQL就会溅射:

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

Rather than looking for publication_contributors.contributor_id, it's looking for publication_contributors.contributor, which doesn't exist. Am I doing something wrong in my code? I can't find any other examples of a where clause with deeply nested associations like this. Perhaps it's not even possible?

而不是寻找publication_贡献者。contributor_id,它正在寻找publication_contributor。贡献者,这根本不存在。我的代码有问题吗?我找不到任何其他带有深度嵌套关联的where子句的例子。也许这根本不可能?

UPDATE:

更新:

The generated SQL

生成的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

Also, I have this association in my Publications model:

另外,我在我的出版物模型中有这样的关联:

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

I was thinking that I could do this:

我想我能做到:

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

But that throws the error:

但这就抛出了一个错误:

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

1 个解决方案

#1


33  

try to change your where clause :

试着改变你的where条款:

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

ActiveRecord api is not extremely consistent here : the arguments for where do not work exactly as those for joins. This is because the arguments for joins do not reflect the underlying SQL, whereas the arguments for where do.

ActiveRecord api在这里并不是非常一致:对于哪些地方的工作与连接的工作不完全一致。这是因为连接的参数不反映底层SQL,而where的参数是。

where accepts an hash whose keys are table names, and values are hashes (that themselves have column names as keys). It just prevents ambiguity when targetting a column that has the same name in two tables.

其中接受键为表名、值为散列(它们本身以列名作为键)的散列。它只是防止在两个表中设置名称相同的列时出现歧义。

This also explains why your second problem arises : the relation authors does not exist.

这也解释了为什么会出现第二个问题:关系作者不存在。

#1


33  

try to change your where clause :

试着改变你的where条款:

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

ActiveRecord api is not extremely consistent here : the arguments for where do not work exactly as those for joins. This is because the arguments for joins do not reflect the underlying SQL, whereas the arguments for where do.

ActiveRecord api在这里并不是非常一致:对于哪些地方的工作与连接的工作不完全一致。这是因为连接的参数不反映底层SQL,而where的参数是。

where accepts an hash whose keys are table names, and values are hashes (that themselves have column names as keys). It just prevents ambiguity when targetting a column that has the same name in two tables.

其中接受键为表名、值为散列(它们本身以列名作为键)的散列。它只是防止在两个表中设置名称相同的列时出现歧义。

This also explains why your second problem arises : the relation authors does not exist.

这也解释了为什么会出现第二个问题:关系作者不存在。