数组::包括哪些内容?在ActiveRecord集合上没有调用op ==?

时间:2010-03-12 03:44:11

标签: ruby-on-rails ruby arrays collections associations

鉴于来自Foo的名为ActiveRecord的集合,为什么Array#include?似乎不会调用Foo.==index呢?

class Foo < ActiveRecord::Base
  def ==(s)
    self.name == s
  end
end

class Bar < ActiveRecord::Base
  has_many :foos
end

bar.foos << Foo.new( :name => 'hmm' )

bar.foos.all.include?('hmm')  # does select all from db every time
=> true

bar.foos.include?('hmm') # does not go to db, but does not find the Foo!
=> false

bar.foos.index('hmm') # does not go to db, but does find the Foo[0] !
=> 0

bar.foos.index('eh') # no such object
=> nil

我对代理人的理解很浅,但是(没有绕过AR源代码)为什么索引似乎表现正确但包括?不是!?

这是代理行为中的错误,和/或是否在某处记录了此行为?

感谢。

2 个答案:

答案 0 :(得分:0)

这是因为bar.foos未返回ActiveRecord::Base个对象,但返回AssociationProxy(请参阅association_proxy.rb)。

我建议您不要在关联代理中重新定义==,否则您将改变应用程序中所有关联的行为。

答案 1 :(得分:0)

西蒙娜,这不是我正在寻找的答案(但我喜欢你的想法; - )

这提示我虽然阅读文档,但association_proxy.rb的源代码(实际上,AssociationCollection模拟了关联返回的集合上的Array方法。)

查看AssociationCollection.include?

 File activerecord/lib/active_record/associations/association_collection.rb, line 332
      def include?(record)
        return false unless record.is_a?(@reflection.klass)
        load_target if @reflection.options[:finder_sql] && !loaded?
        return @target.include?(record) if loaded?
        exists?(record)
      end

看起来arg record应该是@reflection.klass类型,而Array.include?看一个对象并使用在数组对象上定义的==比较器。 / p>

嗯,这不是我想要的AR。既然是Enumerable.member?似乎在协会集合上工作,我只会使用它。我想扫描缓存的集合,而不是再次访问数据库。也许有人可以解释AssociationCollection如何重新映射成员? ?