我使用的是Rails 3.2.0
假设我有:
class Comment < ActiveRecord::Base has_many :articles end c1 = Comment.last
然后
c1.articles.class # => Array c1.articles.where('id NOT IN (999999)').class # => ActiveRecord::Relation
为什么关联的结果不是ActiveRecord :: Relation的一种类型?
显然是/在某个时候:
c1.articles.to_orig # undefined method `to_orig' for #<ActiveRecord::Relation:0x007fd820cc80a8> c1.articles.class # => Array
某些评估对ActiveRecord :: Relation对象采取行动,但检查该类则提供了不同的类型.
解决方法
它是一个ActiveRecord :: Relation,但Rails是故意对你说谎.您可以在方法调用中看到这一点,并通过调用祖先来继续查看它,其中包含一大堆ActiveRecord类:
c1.articles.ancestors.select { |c| c.to_s =~ /ActiveRecord/ }.size #=> 35
这表明它不是一个数组.
这是因为在调用c1.articles时要恢复的是ActiveRecord::Associations::CollectionProxy
*,其中undefines class
(以及许多其他方法).这意味着通过its method_missing
(sends it to target
)委派类.我们可以看到,这里的目标类实际上是Array:
c1.articles.target.class #=> Array
那就是c1.articles.class来自哪里.然而,它是一个ActiveRecord :: Relation.
*我们可以通过在对象的对象上调用Ruby的原始类方法来验证它确实是一个ActiveRecord :: Associations :: CollectionProxy:Object.instance_method(:class).bind(c1.articles).call.这是一个很好的技巧来验证该对象是不是试图假装是一个不同的类.