2012-11-06 10 views
8

In Ruby möchte ich eine Klasse haben eine Reihe von Modulen und haben diese einzelnen Module führen einen Block oder eine Methode (oder nur eine Möglichkeit zum Bearbeiten einer Instanzvariable finden) bei der Initialisierung dieser Klasse. Ich weiß, dass ich dies tun kann, indem ich eine Methode im Modul erstelle und sie dann in der Initialisierungsmethode der Klasse aufruft, aber ich möchte einen Weg finden, indem ich einfach das Modul einschließe und eine Methode aufrufe, um den Code zu initialisieren Auf diese Weise kann ich eine große Menge von Dingen in einer Klasse enthalten, ohne sich Gedanken darüber machen zu müssen, eine Codezeile in der Initialisierungsmethode für jedes einzelne Modul hinzuzufügen. Ich habe Aliasing ausgecheckt, super, und die damit verbundenen Dinge aber haben nichts bekommen ... Wenn es hilft zu verstehen, was ich hoffe, hier zu erreichen ist einige Pseudo-Code:Ruby: Hinzufügen von Dingen zu initialisieren Methode durch Module

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] 

Dies kann ein wenig wortreich aber ich denke, der Titel fasst zusammen, was ich zu tun versuche. Danke für jede Hilfe!

Antwort

7

Es gibt ein paar Möglichkeiten, wie Sie dies tun können. In diesem Beispiel wird die Methode initialize neu definieren und hinzufügen, was zusätzlichen Code Sie wollen:

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 

jedoch: Ich denke, was Sie wirklich wollen, ist Subclassing. Wenn Sie viele Klassen mit ähnlichem Verhalten haben, wie Sie es anscheinend tun, fragen Sie sich, ob es eine natürliche abstrakte Elternklasse gibt. Kannst du erklären, was du mit super gemacht hast und warum es nicht funktioniert hat?

+0

Sie haben Recht, ich schaute in, wie super funktioniert und ich bin in der Lage, Code für eine beliebige Anzahl von Modulen auszuführen, egal welche Kombination oder welche Module. Grundsätzlich eine Kette von Super für die Module gemacht: – thIIIrd

+0

Das ist so Geld, danke. Ich habe dies verwendet, um 'fähigkeit.rb' Dateien für ein Rails CanCan Autorisierungsmuster zu separieren: http://StackOverflow.com/a/25723811/293280 –

Verwandte Themen