制作方法的方法:简单的Ruby元编程

时间:2010-05-17 21:08:03

标签: ruby metaprogramming

我在视图助手

中有很多这样的方法
  def background
    "#e9eaec"
  end
  def footer_link_color
    "#836448"
  end

我希望这些方法暴露在视图中,但我更喜欢帮助器更简洁一些。例如,将哈希转换为方法(或其他方法)的最佳方法是什么?

4 个答案:

答案 0 :(得分:3)

module MyHelper
  {:background => "#e9eaec", :footer_link_color => "#836448"}.each do |k,v|
    define_method(k) {v}
  end
end

虽然我认为对于第一种方法的可读性而言,简单易懂,但这并不是一个好主意。

如果要概括它,可以将以下方法添加到Module类:

class Module
  def methods_from_hash(hash)
    hash.each do |k,v|
      define_method(k) {v}
    end
  end
end

然后在你的帮助电话methods_from_hash(:background => ...)

答案 1 :(得分:3)

如果在命名空间中创建常量,那么您可以轻松地为这些常量添加访问器:

class Foo

  module Values
    FOO = 1
    BAR = 'bar'
    BAZ = :baz
  end
  include Values

  Values.constants.each do |name|
    define_method(name.downcase) do
      Values.const_get(name)
    end
  end

end

foo = Foo.new
p foo.foo    # => 1
p foo.bar    # => "bar"
p foo.baz    # => :baz

为了方便Foo自己的方法,include Values将常量混合到Foo中。这种模式不需要工作。

答案 2 :(得分:2)

实际上,ruby有一个名为OpenStruct的东西,这非常棒,当你想要哈希但又不想像哈希那样使用它时非常有用。

require 'ostruct'

colors = OpenStruct.new({:background => "0x00FF00", :color => "0xFF00FF"})

p colors.background #=> "0x00FF00"

答案 3 :(得分:0)

这是我对sepp2k的答案的混音。它有点多OO,甚至可以在irb中使用。不确定是要修补Object还是Hash

class Hash
  def keys_to_methods()
    each do |k,v|
      self.class.send(:define_method, k,  Proc.new {v});
    end
    length
  end
end

测试代码

hash = {:color_one=>"black", :color_two=>"green"}
hash.keys_to_methods
has.color_one # returns black

OpenStruct :再次感谢sepp2k!我不知道this存在。

这是使用method_missing的另一个版本

class Hash
  def method_missing(method_id)
    key = method_id.id2name
    if has_key?(key)
      return self[key]
    elsif has_key?(key.to_sym)
      return self[key.to_sym]
    else
      super.method_missing(method_id)
    end
  end
end

hash = {:color_one=>"black", :color_two=>"green"}
hash.color_one

我确信我可以让代码更紧密(如果我知道的话)。