views:

27

answers:

1

Can someone explain me this Ruby on Rails puzzle?

 class Post < ActiveRecord::Base
   has_many :comments
 end

 Post.first.comments.class
 => Array

 Array === Post.first.comments
 => false

 Array === [ 1 ]
 => true
+2  A: 

Post.first.comments is a delegator. It does not give you back an Array directly, but if you do anything with it, it turns into one. This is useful because it lets you do stuff like

Post.first.comments.all(:conditions => {:author_name => 'RJH'})

without having to inject those methods into the array object, or extending the Array class.

BaroqueBobcat
OK, thanks. But is there a way how can I actually find out what class is Post.first.comments if even #class method is delegated?
Jakub
you might find this bit of the rails source interesting: http://github.com/rails/rails/blob/2-3-stable/activerecord/lib/active_record/associations/association_proxy.rb
BaroqueBobcat
OK, thanks a lot! Just for those who might stumble upon this thread, quote from the docs: "As a corner case, it even removes the +class+ method and that's why you get 'blog.posts.class # => Array' though the object behind blog.posts is not an Array, but an ActiveRecord::Associations::HasManyAssociation.
Jakub