Basic primer:
class User
has_man开发者_如何学编程y :programs, :through => :memberships
has_many :memberships
end
class Program
end
class Membership
belongs_to :user
belongs_to :program
end
Console:
User.new.save
Program.new.save
User.programs << Program.first
User.first.programs.class
# => Array
User.first.programs.methods.grep /where/
# => []
User.first.programs.where :id => 1
# => [#<Program id: 1>]
User.first.programs.where(:id => 1).class
# => ActiveRecord::Relation
So the question is that User.first.programs
, the has_many method, seems to return a result that barks like an ActiveRecord::Relation
and accepts methods like a Relation
, but self-identifies as an Array
and shares its methods with an instance of class Array
.
So what gives?
It's indeed surprising and don't know if it was the best solution, but at least it's documented (in the AssociationProxy class):
the association proxy in blog.posts has the object in blog as @owner, the collection of its posts as @target, and the @reflection object represents a :has_many macro.
This class has most of the basic instance methods removed, and delegates unknown methods to @target via method_missing. 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.
精彩评论