0

我的印象是custom_finderActiveRecord 中的选项意味着您可以免费获得关联扩展.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不会导致关联扩展尊重它,那么它有什么意义 - 它可能只是对象上的一个方法......

4

1 回答 1

0

这是真实的。我认为自定义查找器是 Rails 中上一代查找器的遗产(在 Arel && AR::Relation 之前),它今天在关联中的存在只是为了向后兼容(恕我直言)。无论如何,它不符合 AR::Relation(扩展)的意识形态。

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

实际上现在,当关联有 :finder_sql 选项时,它仅用于形成记录集合(使用.find_by_sql)。关联创建 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
于 2012-12-27T01:47:59.087 回答