我认为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
不会导致关联扩展尊重它,那么它的重点是什么 - 它可能只是对象的一种方法......
答案 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