2

私はいくつかのメソッドを持つクラスを持っています。supersekret ですが、ここでできることを再現しました。

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

実行時に、メソッドの 1 つについてクラスに問い合わせて、次のようにハッシュまたは構造体を受け取ることができるようにしたいと考えています。

  {:lights => 'red', :confirmation => false, :sound => 'windows'}

これを行う最善の方法は何ですか?もちろん、別々の YAML ファイルを横に置いて、2 つを関連付ける規則を設定することもできますが、コードとメタデータを 1 か所にまとめることが理想的です。

私が思いつく最も有望なアイデアは、次のようなものです。

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 は public です。そのように使用する場合、2 番目のオプションは一貫性が保証されないため、あまり役に立ちません。

于 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

(文書化されていない) hook を使用してこれを管理しModule#method_addedます。それはこのように動作します:

  1. インスタンス変数、 を呼び出してThor#desc設定 します。Thor#method_options@desc@method_options

  2. stun!メソッド呼び出し の定義Thor#method_added(meth)

  3. Thor#method_addedTask.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 に答える