2011-02-15 6 views
1

基本プライマー:has_many関係の実際のクラスは何ですか?

class User 
    has_many :programs, :through => :memberships 
    has_many :memberships 
end 

class Program 
end 

class Membership 
    belongs_to :user 
    belongs_to :program 
end 

コンソール:

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 

そこで質問がUser.first.programs、has_manyの方法は、ActiveRecord::Relationのように樹皮やRelationのようなメソッドを受け入れ、結果を返すように見えるということですが、自己識別はArrayとし、そのメソッドをクラスArrayのインスタンスと共有します。

だから何ですか?

答えて

4

それは確かに驚くべきだし、それが最善の解決策だったかどうか知りませんが、少なくともそれは(AssociationProxyクラスで)文書化されています:

blog.posts における関連プロキシがブログで目的としています@投稿者のように投稿の のコレクションは@ターゲット、 、@reflectionオブジェクトは a:has_manyマクロを表します。

このクラスでは、基本的な インスタンスメソッドのほとんどが削除されていて、method_missingを経由して を@targetする 代表者不明の方法。コーナーケース、 としてそれもblog.posts背後 オブジェクトが アレイが、 ActiveRecordのではないですが、あなたは

blog.posts.class#=>配列を得る理由ですクラスメソッドと を削除します。 :アソシエーション:: HasManyAssociation。

+0

確かに、Rails(とRubyについては問題ありません)の一部です。もちろん、フォローアップの問題は次のようなものです。ドキュメンテーションのために祈る以外に、この状況をどのように処理しますか?これについては、ここでそれほどの質問があります:http://stackoverflow.com/questions/5446331/metaprogramming-how-to-discover-the-real-class-of-an-object – Chinasaur

+0

Rubyの暗い魔法はデザインによってもたらされ、それは大丈夫ですだから、私はこの種の問題を避ける最善の方法は単に "しないでください"と言います。私はチェックしませんでしたが、Rails 3ではこれとは別のやり方があると思います。 – tokland

+0

ダークマジックが大丈夫だと知っている限り、私は同意します。しかし、それが起こったときには恐ろしく、十分に文書化されていないので、これらの状況を検出して作業するための信頼できる方法があればうれしいでしょう。本当のクラスを取得する方法が必要なような気がします。 – Chinasaur

関連する問題