2017-06-01 7 views
-1

私の関係にある<<セッターをオーバーライドしたいと思います。例えば、与えられた:関係のアクティブレコードセッターをオーバーライドするレール

class Library < ActiveRecord::Base 
    has_many :groups 

    def readers 
    groups.find_by(name: 'readers').users 
    end 
end 

class Group < ActiveRecord::Base 
    has_many :group_memberships 
    has_many :users, through: :group_memberships 
end 

class GroupMembership < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :group 
end 

class User < ActiveRecord::Base 
    has_many :groups, through :group_membership 
end 

を私は

someLibrary.readers << user1 

と、この後に起こるために、いくつかの追加のもののような何かをしたいです。

コードは次のようになります。

それがあるべき
def <<(objects) 
    super objects 
    #do other things here 
end 

を?私は次のように、Groupに推測:

class Group 
    ... 
    def users<<(objects) 
    super objects 
    #do stuff 
    end 
end 

が、私は読者に<<を呼び出すだとき、私はそれをやってみたいです。

グループユーザーの関係で<<を呼び出しているかどうかを知る方法があるかどうか、またはグループユーザーに対して<<メソッドを呼び出すときにグループオブジェクトにアクセスできるかどうかを知りたい。

いいですね。最も簡単な方法は、読者を設定する別のメソッドを定義することです(より明示的にする)が、activerecordまたはrubyで可能かどうかを知りたい。

編集:

うん、私はコアメソッドをオーバーライドすることは悪いことであり、人々はそのために地獄に行くことを知って、矢田矢田矢田。

私はちょうどそれが完了したのか興味があります。同様に、学習目的のために。

その目的は、特定の関係について<<メソッドをオーバーライドするだけで、誰かがそれをやりたいと思うかもしれない理由を正当化する可能性があります。

+0

あなたのバージョンの 'AR'では' someLibrary.readers.class'とは何ですか? – mudasobwa

+0

IMHO Railsメソッドをオーバーライドするのはひどい考えです。なぜ実際に何を反映している名前で新しいメソッドを追加しないのですか? Railsのコアメソッドをオーバーライドすることで、何を達成しようとしていますか? – spickermann

答えて

1

必須免責事項:

私が '重要' のコードで、あなたがこのを行うことをお勧めしません。このようなメソッドの振る舞いを変更すると、他の開発者(将来の自己と同様)の混乱を招き、あらゆる種類の意図しない振る舞いの変化につながります!

しかし、これはただ楽しみのため」であると仮定すると...

Userレコードのコレクションを返しますsomeLibrary.readers上記の情報に基づいて。だから、私たちがする必要があるのは、そのクラスに望ましい振る舞いを加えることだけです。

someLibrary.readers.foo 
someLibrary.readers.bar 
:あなたのようなメソッドを呼び出すことができ、代わりに上記で

class User 
    def self.foo 
    puts 'this works!' 
    end 

    class << self 
    def bar 
     puts 'this works too!' 
    end 
    end 
end 

通常あなただけの2つの方法のいずれかで、クラスメソッドを定義することによってこれを行うことができます

...しかし、そこにはいくつかのレール黒魔法が続いています。someLibrary.readersは実際にはUser::ActiveRecord_Associations_CollectionProxyのインスタンスであり、上記のメソッドは動的に取得され、ActiveRecord::Associations::CollectionProxyに追加されます。

ダイナミックメソッド定義のため、この方法で既存のRailsメソッド(<<など)を上書きすることはできません。あなたはしかし、これを行うためのより良い方法を探しているなら、私はサービス対象デザインパターンを使用することをお勧めしたい、

class User 
    class ActiveRecord_Associations_CollectionProxy 
    def <<(objects) 
     super(objects) 
     # do stuff 
    end 
    end 
end 

:代わりに、私たちは、サル・パッチに直接User::ActiveRecord_Associations_CollectionProxyクラスが必要になります。次に、ユーザー、ライブラリなどの作成/更新/削除に関連する複雑な/カスタムの論理を、きれいに分離した抽象的にカプセル化することができます。

0

これを行うには、より確立された方法...

class Library < ActiveRecord::Base 
    has_many :groups 
    has_one :reader_group -> {groups.find_by(name: 'readers')} 
    has_many :readers, through: :reader_group, class_name: 'User', foreign_key: 'user_id' 
end 

そして、それはそれです。あなたは今できるです

my_library.readers << another_user 
+0

これは良いコード改善ですが、実際に質問に答えることはありませんか?... –

関連する問題