我有一个使用自定义类型的DSL(从基元继承的对象,即String
),但我不想用它们污染全局命名空间,因为它们仅用于一些地方,没有其他地方。
如果我尝试将Types包装在与DSL执行上下文相同的模块名称空间中,我会得到NameError
,uninitialized constant
。我还试过包含包装类型的模块,甚至对Object
类使用了改进,但没有任何作用。
由于问题的(相对)复杂性,我不确定这是否是你需要帮助我的,所以我猜测。
module Forms
class Define
class << self
attr_accessor :forms
def draw name, &script
@forms[name] = new(&script)
end
end
def initialize &description
@meta = {}
@section_counter = 0
self.tree = Tree.new
instance_eval &description
end
end
end
并像这样使用:
Forms::Define.draw 'Register' do
#some dsl code...
end
编辑:谢谢,没有任何方式注意到错字。
由于人们似乎并不理解&#34;我有一个使用自定义类型的DSL&#34;并且&#34;我不想用它们污染全局命名空间&#34;我将更具体地说明问题。
我说我的类型是这样的:
class Some_Custom_Type < String
end
但是这样做会污染全局命名空间,所以如果我命名这样的类型:
module Forms
class Some_Custom_Type < String
end
end
然后尝试使用它:
Forms::Define.draw 'Register' do
some_code_using Some_Custom_Type
#some dsl code...
end
它会报错uninitialized constant Some_Custom_Type (NameError)
所以我再一次问清楚,在没有污染全局命名空间的情况下,如何确保Some_Custom_Type
可用,而不会污染全局命名空间?
答案 0 :(得分:1)
我不确定我是否理解这个问题,但可能会有所帮助:
@forms[name] = const_set(
name,
Class.new(Object) do |c|
c.send :define_method, :initialize, *args, &script
end
)
致电Forms::Define.draw 'Register'
后,您将获得一个班级Forms::Define::Register
,可以随时随地使用。
答案 1 :(得分:1)
我通过创建界面解决了这个问题。
从OP中的例子给出:
module Forms
module Types
class Some_Custom_Type < String
end
end
end
我补充说:
module Forms
module Types_Wrapper
def some_custom_type
Some_Custom_Type
end
end
def self.included(child)
child.include Types_Wrapper
end
end
像这样添加:
module Forms
class Define
include Types
end
end
可以像这样使用:
Forms::Define.draw 'Register' do
some_code_using some_custom_type
#some dsl code...
end
在:
Forms::Define.draw 'Register' do
some_code_using Some_Custom_Type
#some dsl code...
end
差异很小,但现在可以运行,而且我感觉更像DSL。