2010-03-02 12 views
7

Czy można zmienić powiązanie procedury podczas czasu wywołania?Zmiana wiązania `Proc` podczas wywołania

class AllValidator 
    def age_validator 
    Proc.new {|value| self.age > value } 
    end 
end 

class Bar 
    attr_accessor :age 
    def doSomething 
    validator = AllValidator.new.age_validator 
    validator.call(25) # How to pass self as the binding? 
    end 
end 

W powyższym kodzie, jak zmienić powiązanie proc podczas wywoływania? Czy istnieje sposób przekazania wiązania podobnie jak funkcja eval?

Uwaga Jeżeli powyższy przykład były prawdziwe, użyłbym mixin/inheritence itd. Używam kod do wykazania mój scenariusz problemu.

Odpowiedz

12

Można użyć instance_eval:

class Bar 
    def do_something 
    validator = AllValidator.new.age_validator 

    # Evaluate validator in the context of self. 
    instance_eval &validator 
    end 
end 

Jeśli chcesz przekazać argumentów (jak wspomniano w komentarzu poniżej), można użyć instance_exec zamiast instance_eval jeśli używasz Ruby 1.9 lub Ruby 1.8.7:

class Bar 
    def do_something 
    validator = AllValidator.new.age_validator 

    # instance_exec is like instance_eval with arguments. 
    instance_exec 5, &validator 
    end 
end 

Jeśli masz, aby pracować z Ruby 1.8.6 i poniżej, jak również, najlepiej jest powiązać proc jako metoda Bar:

class Bar 
    def do_something 
    self.class.send :define_method, :validate, &AllValidator.new.age_validator 
    self.validate 5 
    end 
end 

Alternatywą jest wdrożenie starszych wersji Ruby instance_exec (example here). Wszystko, co robi, to zdefiniowanie metody przed wywołaniem jej i jej niezdefiniowanie po zakończeniu.

+0

Czy to pozwala przekazać argument do "walidatora"? –

+0

'instance_eval' ma siostrzaną metodę, która pozwala to zrobić, patrz aktualizacja powyżej. – molf

+0

+1 Dziękujemy za szczegółową odpowiedź. –

Powiązane problemy