2017-03-18 1 views
1

Ein Benutzer meiner Ruby-DSL möchte der Lage sein, zusätzliche Methoden hinzufügen und sie im Rahmen eines beliebigen Block, zum Beispiel aufrufen:Ruby-DSL - Benutzer bereitgestellte Methoden im Block Kontext Aufruf

def do_something 
    override 'flags', 'ABC'   
end 

project('XXX') do 
    configuration('debug') do 
    do_something 
    end 
end 

In Dieses Beispiel, 'override', ist eine Methode des Konfigurationsobjekts, das mit instance_eval aufgerufen wird.

Gibt es eine Möglichkeit, Methodenaufrufe im Kontext des Konfigurationsblocks zu erzwingen, so dass beispielsweise 'override' aufgelöst und ausgeführt werden kann?

[Bearbeiten]

ich das Root-DSL-Objekt So konstruieren und bewerten, wie folgt:

root_dsl = DSL.new 
root_dsl.instance_eval(File.read(filename)) 

Diese DSL-Klasse eine Methode für sie passenden 'Projekt' aus dem obigen Beispiel hat:

def project(&block) do 
    project_dsl = ProjectDSL.new 
    project_dsl.instance_eval(&block) 
end 

Und die project_dsl Klasse hat eine Methode auf sie ‚Konfiguration‘ aus dem obigen Beispiel passend:

def configuration(name, &block) do 
    configuration_dsl = ProjectConfigDSL.new(name) 
    configuration_dsl.instance_eval(&block) 
end 

Und so weiter. Der Benutzer möchte, dass seine definierte Methode in der DSL-Datei selbst im Kontext des ProjectConfigDSL-Objekts ausgeführt wird.

+0

Würde es Ihnen etwas ausmachen, die DSL-Implementierung selbst zu teilen? – mudasobwa

+0

@mudasobwa Ich habe weitere Implementierungsdetails wie gewünscht hinzugefügt – lyptt

Antwort

0

Die Art, wie ich das in meinem eigenen Code mache, ist, dass die Hilfsfunktion einen Proc zurückgibt, der an instance_eval übergeben wird. zum Beispiel:

def do_something 
    Proc.new do 
    override 'flags', 'ABC' 
    end   
end 

project('XXX') do 
    configuration 'debug', &do_something 
end 
0

So war ich nicht bewusst, dass instance_eval Sandkästen Umfang an die erste Instanz, also was ich habe, ist, Delegierter von der Wurzel DSL-Objekt mit dem Block direkt ausführt und Anrufe in missing_method an ein Kind weiterzuleiten DSL-Objekt, und wiederhole dieses Muster den ganzen Weg nach unten.

Dadurch behebt es das Problem des Bereichs, aber es verursacht ein neues Problem von kollellierenden Methodennamen, die an die falschen Objekte weitergeleitet werden. Zum Glück ist mein DSL noch nicht in das Problem geraten, also wird das für jetzt gut genug sein.

Verwandte Themen