2

我有一堂有一些方法的课。这是超级秘密,但我已经在这里复制了我能做到的。

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

有人有更好的想法吗?我在吠叫一棵非常错误的树吗?

4

3 回答 3

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 是公共的,如果您打算以这种方式使用它,那么第二个选项变得不太有用,因为它不能确保一致性。

于 2009-01-14T16:57:36.740 回答
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。它是这样工作的:

  1. 调用Thor#descThor#method_options设置实例变量@desc, @method_options.

  2. 定义方法stun!调用 Thor#method_added(meth)

  3. Thor#method_added注册 Task.new(meth.to_s, @desc, @method_options)(粗略地说)和取消设置@desc, @method_options.

  4. 现在已经为下一个方法做好了准备

整洁的!如此整洁,我将接受我自己的答案:)

于 2009-03-26T14:43:36.153 回答
1

YARD工具可让您将元数据添加到方法中。我很确定它只是将元数据粘贴到rdoc您生成的文件中,但是您可以轻松地以此为基础来获取运行时信息。

于 2009-01-14T16:58:30.623 回答