将 procs 与 Ruby 的 DSL 一起使用
为了用户方便和更干净的代码,我想编写一个可以像这样使用的类:
Encoder::Theora.encode do
infile = "path/to/infile"
outfile = "path/to/outfile"
passes = 2
# ... more params
end
现在的挑战是,在我的编码方法中提供该参数。
module Encoder
class Theora
def self.encode(&proc)
proc.call
# do some fancy encoding stuff here
# using the parameters from the proc
end
end
end
这种方法行不通。当调用 Proc 时,变量不会在 Theora 类的上下文中计算。通常我想使用 method_missing 将每个参数放入 Theora 类的类变量中,但我找不到正确的条目方法。
有人能指出我正确的方向吗?
For user convenience and more clean code I would like to write a class that can be used like this:
Encoder::Theora.encode do
infile = "path/to/infile"
outfile = "path/to/outfile"
passes = 2
# ... more params
end
The challenge now is, to have that parameters available in my encode method.
module Encoder
class Theora
def self.encode(&proc)
proc.call
# do some fancy encoding stuff here
# using the parameters from the proc
end
end
end
This approach does not work. When the Proc is called, the variables are not evaluated in the context of the Theora class. Usually I would like to use method_missing to put every parameter into a class variable of class Theora, but I do not find the right way for an entry.
Can anyone point me into the right direction?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我不确定是否可以让 DSL 使用赋值,我认为 Ruby 解释器总是假设
infile = 'path/to/something'
中的infile
是该上下文中的局部变量(但可以使 self.infile = 'path/to/something' 起作用)。但是,如果您可以接受没有该特定细节的情况,则可以像这样实现 DSL:并像这样使用它:(
类似地实现其他属性)。
I'm not sure it's possible to get the DSL to use assignment, I think the Ruby interpreter will always assume that
infile
ininfile = 'path/to/something'
is a local variable in that context (butself.infile = 'path/to/something'
can be made to work). However, if you can live without that particular detail, you can implement your DSL like this:and use it like this:
(implement the other properties similarily).
AFAIK,它不能按照您编写的方式完成。过程的主体有自己的作用域,在该作用域内创建的变量在其外部不可见。
惯用的方法是创建一个配置对象并将其传递到块中,该块描述了使用该对象的方法或属性要完成的工作。然后在工作时读取这些设置。例如,ActiveRecord 迁移中
create_table
就采用了这种方法。所以你可以这样做:
It can't be done the way you've written it, AFAIK. The body of the proc has its own scope, and variables that are created within that scope are not visible outside it.
The idiomatic approach is to create a configuration object and pass it into the block, which describes the work to be done using methods or attributes of that object. Then those settings are read when doing the work. This is the approach taken by
create_table
in ActiveRecord migrations, for example.So you can do something like this:
在尝试这个过程中,我得到了以下内容,我不一定推荐它,并且它不太符合所需的语法,但它确实允许您使用赋值(某种程度)。因此,请本着完整的精神仔细阅读:
我相信 Binding.eval 仅适用于 Ruby 1.9。另外,似乎局部变量需要在屈服之前声明,否则它将不起作用——有人知道为什么吗?
In playing around with this I arrived at the following, which I don't necessarily recommend, and which doesn't quite fit the required syntax, but which does allow you to use assignment (sort of). So peruse in the spirit of completeness:
I believe Binding.eval only works in Ruby 1.9. Also, it seems the local variables need to be declared before yielding or it won't work -- anyone know why?
好吧,首先我必须说 pmdboi 的答案非常优雅,而且几乎可以肯定是正确的。
不过,万一你想要一个超级精简的 DSL,比如
你可以做一些像这样的丑陋的事情:
OK, first I must say that pmdboi's answer is very elegant and almost certainly the right one.
Still, just in case you want a super cut-down DSL like
You can do something ugly like this: