我有一个有一些方法的课。这是超级巨星,但我已经复制了我能在这里发现的东西。
Class RayGun
# flashes red light
# requires confirmation
# makes "zowowowowowow" sound
def stun!
# ...
end
# flashes blue light
# does not require confirmation
# makes "trrrtrtrtrrtrtrtrtrtrtr" sound
def freeze!
# ...
end
# doesn't flash any lights
# does not require confirmation
# makes Windows startup sound
def killoblast!
# ...
end
end
我希望能够在运行时查询有关其中一个方法的类,并接收类似的哈希或结构:
{:lights => 'red', :confirmation => false, :sound => 'windows'}
这样做的最佳方法是什么?显然你可以同时拥有单独的YAML文件,并设置一个约定两者的约定,但理想情况下我想在一个地方使用代码和元数据。
我能提出的最有希望的想法是这样的:
class RayGun
cattr_accessor :metadata
def self.register_method(hsh)
define_method(hsh.name, hsh.block)
metadata[hsh[:name]] = hsh
end
register_method({
:name => 'stun!',
:lights => 'red',
:confirmation => 'true',
:sound => 'zowowo',
:block => Proc.new do
# code goes here
})
# etc.
end
有人有更好的想法吗?我咆哮着一棵非常错的树吗?
答案 0 :(得分:2)
只是一点点美化:
class RayGun
cattr_accessor :metadata
def self.register_method(name, hsh, &block)
define_method(name, block)
metadata[name] = hsh
end
register_method( 'stun!',
:lights => 'red',
:confirmation => 'true',
:sound => 'zowowo',
) do
# code goes here
end
# etc.
end
您确实无法轻松访问原始闭包,但可能不需要它。
要回答这个问题,它看起来并不坏,你可以做一些更多的会议,但可能已经足够好了:
class RayGun
cattr_accessor :metadata
@metadata[:stun!] = {:lights => 'red',
:confirmation => 'true',
:sound => 'zowowo'}
def stun!
# ...
end
# etc.
end
在原始示例中,register_method是公共的,如果您计划以这种方式使用它,则第二个选项变得不那么有用,因为它不能确保一致性。
答案 1 :(得分:2)
我找到了围绕http://github.com/wycats/thor/tree的另一个策略。 Thor让你写这样的东西:
Class RayGun < Thor
desc "Flashes red light and makes zowowowowow sound"
method_options :confirmation => :required
def stun!
# ...
end
end
它通过使用(未记录的)钩子Module#method_added
来管理它。它的工作原理如下:
致电Thor#desc
和
Thor#method_options
设置实例
变量@desc
,
@method_options
。
定义方法stun!
调用
Thor#method_added(meth)
Thor#method_added
个寄存器
Task.new(meth.to_s, @desc,
@method_options)
(粗略地说)
并取消@desc
,
@method_options
。
现在已经为下一个方法做好了准备
纯!如此整洁,我将接受我自己的答案:)
答案 2 :(得分:1)
有YARD工具可让您向方法添加元数据。我很确定它只是将元数据粘贴到您生成的rdoc
文件中,但您可以轻松地构建它以获取运行时信息。