2010-05-17 11 views
4

我有很多这样的方法在视图助手制法方法:简单的Ruby元编程

def background 
    "#e9eaec" 
    end 
    def footer_link_color 
    "#836448" 
    end 

我想这些方法容易看到,但我更喜欢的帮手是一个一点更简洁。将哈希变成方法(或其他方法)的最佳方式是什么?

回答

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

虽然我不认为交易这一点简洁为您的第一种方法的可读性是一个好主意。

如果要概括这一点,你可以在下面的方法添加到模块类:

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

,然后在助手呼吁methods_from_hash(:background => ...)

+0

实际上,如果您将散列和猴子补丁用于模块类,它会更干净。我挺喜欢它的。谢谢。 – 2010-05-18 01:57:13

+0

我在下面的“答案”中重新混合了你的答案......虽然我需要弄清楚在原始问题(帮助者)的上下文中哪个版本更好。 – 2010-05-22 08:31:12

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 

include Values混合常数为富为Foo的自己的方法的便利。这种模式不需要工作。

+0

Ruby知道他们是常量,或者仅仅是一个约定? – 2010-05-17 22:43:30

+0

@yar,Ruby知道我们正在定义一个常量,因为标识符以大写字母开头。它如何跟踪什么是常数,什么不是,我不知道。 – 2010-05-17 22:51:05

+0

对于Ruby来说,这是一个令人啼笑皆非的悲哀事实:它很多都是用非Ruby编写的,除非你想进入C语言之下,否则很难知道所有这些东西。感谢您的回答。 – 2010-05-18 00:02:02

0

这是我sepp2k答案的混音。这是一个更多的面向对象和工作,即使在irb。不知道是否补丁ObjectHash

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 

我相信我能得到的代码更严格的另一个版本(如果我知道如何)。

+0

修补对象没有任何意义,因为这只会对至少具有每种方法的对象起作用(所以至少Enumerable)。还要注意,如果你想要的只是一个散列,你可以通过使用'hash.key'而不是'hash [key]'来获得key的值,你可以使用OpenStruct(或者使用'method_missing' )。 – sepp2k 2010-05-22 10:55:06

+0

谢谢@ sepp2k,我用method_missing实现,但我不知道如何优雅地处理键符号或字符串。 – 2010-05-23 08:26:15

2

实际上,ruby有一些叫做OpenStruct的东西,这对于想要散列但不想像一个散列时使用它非常棒和真正有用。

require 'ostruct' 

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

p colors.background #=> "0x00FF00" 
+0

感谢vava,昨天我了解到了这一点,这要感谢sepp2k对我的回答(在某处)的评论。 – 2010-05-23 09:15:30