2010-03-02 16 views
7

Kann die Bindung einer Prozedur während der Aufrufzeit geändert werden?Ändern der "Proc" -Bindung während des Aufrufs

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 

Im Code oben, wie ändere ich die Bindung des Proc während des Aufrufs? Gibt es eine Möglichkeit, die Bindung ähnlich wie die eval Funktion zu übergeben?

Hinweis Wenn das obige Beispiel real wäre, würde ich mixin/inheritence usw. ich den Code bin mit meinem Problem Szenario zu demonstrieren.

Antwort

12

können Sie verwenden instance_eval:

class Bar 
    def do_something 
    validator = AllValidator.new.age_validator 

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

Wenn Sie Argumente übergeben wollen (wie im Kommentar unten erwähnt) können Sie instance_exec statt instance_eval verwenden, wenn Sie Ruby-verwenden 1.9 oder 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 

Wenn Sie müssen es mit Ruby-1.8.6 und unten als auch, Ihre beste Wette ist, funktioniert das proc als Methode der Bar zu binden:

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

Eine Alternative ist instance_exec ältere Ruby-Versionen (example here) zu implementieren. Sie definieren nur eine Methode, bevor Sie sie aufrufen, und definieren sie dann, nachdem Sie fertig sind.

+0

Können Sie damit ein Argument an "Validator" übergeben? –

+0

'instance_eval' hat eine Schwestermethode, mit der Sie das tun können, siehe Update oben. – molf

+0

+1 Danke für die ausführliche Antwort. –

Verwandte Themen