【发布时间】:2010-05-17 21:08:02
【问题描述】:
我在视图助手中有很多这样的方法
def background
"#e9eaec"
end
def footer_link_color
"#836448"
end
我希望将这些方法暴露给视图,但我希望助手更简洁一些。例如,将散列转换为方法(或其他东西)的最佳方法是什么?
【问题讨论】:
标签: ruby metaprogramming
我在视图助手中有很多这样的方法
def background
"#e9eaec"
end
def footer_link_color
"#836448"
end
我希望将这些方法暴露给视图,但我希望助手更简洁一些。例如,将散列转换为方法(或其他东西)的最佳方法是什么?
【问题讨论】:
标签: ruby metaprogramming
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 => ...)。
【讨论】:
如果您在命名空间中创建常量,那么您可以轻松地为这些常量创建访问器:
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 中以方便 Foo 自己的方法。这种模式不需要工作。
【讨论】:
static final 是一种语言功能,因此不是用 Java 编写的。所以在这种情况下你是对的。
实际上,ruby 有一个叫做OpenStruct 的东西,当你想要散列但又不想像散列一样使用它时,它非常棒并且非常有用。
require 'ostruct'
colors = OpenStruct.new({:background => "0x00FF00", :color => "0xFF00FF"})
p colors.background #=> "0x00FF00"
【讨论】:
这是我对 sepp2k 答案的混音。它有点面向对象,甚至在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
我确信我可以让代码更紧凑(如果我知道怎么做的话)。
【讨论】:
hash.key 而不是 hash[key] 获取键的值,您可以只使用 OpenStruct(或带有 method_missing 的猴子补丁哈希)。