你可以使用自定义finder_sql在对象上使用关联扩展吗?

时间:2012-12-26 22:10:54

标签: ruby-on-rails activerecord finder-sql

我认为ActiveRecord中的custom_finder选项意味着您可以免费获得.where.order等关联扩展程序,例如:

class Dog < ActiveRecord::Base
  has_many :fleas, class_name: 'Flea', 
           finder_sql: "select fleas.* from fleas where pet_type = 'dog'"
end

认为这不是一个很好的例子,因为'finder_sql'是如此微不足道,但它说明了这一点。

生成SQL

我希望以下

@dog = Dog.find(5)
@dog.fleas.where('num_legs > 2')

生成

"select fleas.* from fleas where pet_type = 'dog' AND num_legs > 2

即。自定义finder_sql + where子句

然而它实际生成的是

"SELECT "base_posts".* FROM "fleas" WHERE "fleas"."dog_id" = 5 AND (num_legs > 2)

即。它完全忽略了自定义finder_sql并尝试将跳蚤加入当前的狗。

如果自定义finder_sql不会导致关联扩展尊重它,那么它的重点是什么 - 它可能只是对象的一种方法......

1 个答案:

答案 0 :(得分:0)

这是事实。我认为自定义查找器是Rails中前一代查找程序的遗留(在Arel&amp;&amp; AR :: Relation之前),它在协会中的存在只是为了向后兼容(imho)。无论如何,它不符合AR :: Relation(扩展)的意识形态。

到目前为止,我们有 .find_by_sql(),我们有:finder_sql 作为关联选项。

实际上,当关联具有:finder_sql选项时,它仅用于形成记录集合(使用 .find_by_sql )。 Association创建AR :: Relation对象,加载集合(.target)并将AR :: Relation方法调用委托给关系对象,但是它不知道任何自定义SQL语句,只知道主SQL表达式。这就是原因:

@dog.fleas.class
#=> Array
@dog.fleas.to_sql # delegated to AR::Relation

返回主表达式“SELECT”base_posts“。* FROM ...”和

@dog.fleas.where("...") # delegated to AR::Relation

强加新条件,好像没有自定义查找程序一样。

另一方面,由于 .find_by_sql 总是返回一个数组,因此可以使用Array的方法来强加新的条件。

 @dog.fleas.select {|r| ... } # delegated to Array