2017-03-18 44 views
1

我的紅寶石DSL的用戶希望能夠添加額外的方法和任意塊的上下文中調用它們,例如:紅寶石DSL - 調用塊範圍內的用戶提供的方法

def do_something 
    override 'flags', 'ABC'   
end 

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

在這個示例'override'是一個用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的過程。例如:

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

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

所以我不知道instance_eval的沙箱範圍,該實例,所以我不得不做的是從根DSL對象代表與missing_method直接執行塊和轉接電話到孩子DSL對象,然後重複這個模式。

通過這樣做可以修復範圍問題,但確實會導致將collliding方法名稱轉發給錯誤對象的新問題。幸運的是,我的DSL還沒有遇到這個問題,所以現在這已經夠好了。