2012-11-06 8 views
8

W Ruby chcę, aby klasa zawierała serię modułów i te poszczególne moduły wykonują blok lub metodę (lub po prostu znajdź jakiś sposób na edycję zmiennej instancji) podczas inicjowania tego klasa. Wiem, że mogę to zrobić, tworząc metodę w module, a następnie wywołując ją w metodzie inicjalizacji klasy, ale chcę w jakiś sposób to zrobić, po prostu włączając moduł i wywołując jedną metodę do wykonania dowolnego kodu dodawanego przez moduły w celu zainicjowania w ten sposób mogę mieć dużą ilość rzeczy zawartych w klasie bez martwienia się o dodanie linii kodu w metodzie inicjalizacji dla każdego dołączonego modułu. Mam wyrejestrowany aliasingu, super i podobnych rzeczy, ale nie dostał nic ... Jeśli to pomaga zrozumieć, co mam nadzieję osiągnąć tutaj jakiś pseudokod:Ruby: Dodawanie rzeczy do zainicjowania metody za pomocą modułów

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] 

To może być nieco rozwlekły ale myślę, że tytuł podsumowuje to, co próbuję zrobić. Dzięki za pomoc!

Odpowiedz

7

Istnieje kilka sposobów na zrobienie tego. Ten przykład będzie przedefiniować sposób przygotować i dodać dodatkowy kod cokolwiek chcesz:

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 

Jednakże: myślę, co naprawdę chcesz to podklasy. Jeśli masz dużo zajęć o podobnym zachowaniu, jak ci się wydaje, zadaj sobie pytanie, czy istnieje naturalna abstrakcyjna klasa rodziców. Czy możesz wyjaśnić, co zrobiłeś z super i dlaczego to nie zadziałało?

+0

Masz rację, przyjrzałem się, jak super działa i mogę wykonać kod dla dowolnej liczby modułów dodanych bez względu na kombinację lub moduły. Zasadniczo stworzyłem łańcuch supersów dla modułów: – thIIIrd

+0

To są pieniądze, dziękuję. Użyłem tego do oddzielenia plików 'ability.rb' dla wzorca autoryzacji Rails CanCan: http://stackoverflow.com/a/25723811/293280 –