2017-03-18 1 views
1

:でルビーDSL - ブロックのコンテキスト内でユーザが提供するメソッドを呼び出す私のRuby DSLのユーザは、例えば、追加のメソッドを追加し、任意のブロックのコンテキスト内でそれらを呼び出すことができるように望む

def do_something 
    override 'flags', 'ABC'   
end 

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

このサンプルの「オーバーライド」は、instance_evalで呼び出される構成オブジェクトのメソッドです。

コンフィギュレーションブロックのコンテキスト内でメソッド呼び出しを強制的に実行する方法があるため、たとえば「オーバーライド」を解決して実行できますか?

[編集]

だから私は、ルートDSLオブジェクトを作成し、次のように評価します

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

このDSLクラスは、上記のサンプルから「プロジェクト」をマッチング、それにメソッドを持っています

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

project_dslクラスには、上記の例の 'configuration'と一致するメソッドがあります。

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

など。ユーザは、DSLファイル自体の定義済みメソッドがProjectConfigDSLオブジェクトのコンテキスト内で実行されることを望んでいます。

+0

DSL実装自体を共有してもよろしいですか? – mudasobwa

+0

@ mudasobwa私は要求どおりに実装の詳細を追加しました – lyptt

答えて

0

自分のコードでこれをやっているのは、ヘルパー関数がinstance_evalに渡されるprocを返すようにすることです。例えば:

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

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

は、だから私は、そのインスタンスに気付いていないことinstance_evalをサンドボックスの範囲だったので、私は何をしなければならなかったことは、直接ブロックを実行し、子供にmissing_method中のコールを転送すると、ルートDSLオブジェクトから委任されDSLオブジェクトを作成し、このパターンを下方向に繰り返します。

このようにすると、スコープの問題は解決されますが、メソッドの名前が間違ったオブジェクトに転送されるという新たな問題が発生します。幸いにも私のDSLはその問題にまだ踏み込んでいないので、これは今のところ十分です。

関連する問題