2012-11-06 2 views
8

Rubyでは、クラスに一連のモジュールが含まれていて、その個々のモジュールでブロックまたはメソッドを実行する(またはインスタンス変数を編集する方法を見つける)クラス。私はモジュールでメソッドを作成し、それをクラスのinitializeメソッドで呼び出すことでこれを行うことができますが、モジュールを追加して、モジュールが初期化するために追加するコードを実行するメソッドを呼び出すだけで、そうすれば、クラスに含まれる大量のものを、すべての単一モジュールに含まれるinitializeメソッドのコード行を追加することなく心配する必要がなくなります。Ruby:モジュールを使ってメソッドを初期化するものを追加する

module Mod1 
    call_this_block_on_initialize { @a.push 4 } 
end 

module Mod2 
    call_this_block_on_initialize { @a.push 5 } 
end 

class Test 
    attr_accessor :a 
    include Mod1 
    include Mod2 

    def initialize 
     @a = [1, 2, 3] 
     call_those_blocks_set_by_mods 
    end 
end 

t = Test.new 
t.a # returns [1, 2, 3, 4, 5] 

これは少しくどいかもしれ:私はエイリアシング、スーパー、および関連するものをチェックアウトしましたが、それは私がここに達成するために望んでいるかを理解するのに役立ちます場合は...何ももらっていないいくつかの擬似コードですしかし私はタイトルが私がしようとしていることを要約すると思う。助けてくれてありがとう!

答えて

7

これを行う方法はいくつかあります。この例では、initializeメソッドを再定義し、必要な余分なものは何でもコードを追加します:

module MyModule 
    def self.included(base) # built-in Ruby hook for modules 
    base.class_eval do  
     original_method = instance_method(:initialize) 
     define_method(:initialize) do |*args, &block| 
     original_method.bind(self).call(*args, &block) 
     @a.push 4 # (your module code here) 
     end 
    end 
    end 
end 

class Test 
    attr_accessor :a 

    def initialize 
    @a = [1, 2, 3]  
    end 

    # It must be included after the `initialize` 
    # definition or the module won't find the method: 
    include MyModule 
end 

しかし: 私はあなたが本当にしたいことは、サブクラス化だと思います。同じような振る舞いを持つクラスがたくさんある場合は、自然な抽象的な親クラスがあるかどうか自問してください。あなたはsuperで何をしたのか、なぜそれがうまくいかなかったのか説明できますか?

+0

あなたはそうです、私はスーパーがどのように動作するかを調べました。どのような組み合わせやどのモジュールに関係なく、いくつのモジュールを追加してもコードを実行できます。基本的にモジュールのためのスーパーのチェーンを作った: – thIIIrd

+0

これはお金です、ありがとうございます。私はこれを使ってRails CanCan認証パターンのための 'ability.rb'ファイルを分離しました:http://stackoverflow.com/a/25723811/293280 –

関連する問題