2010-05-17 4 views
4

У меня есть куча методов, как это вид помощникаСпособ изготовления Методы: Easy Рубин Метапрограммирование

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

На самом деле было бы более чистым, если бы вы использовали переменную для хэша и паттерна обезьяны для класса модуля. Мне это очень нравится. Благодарю. –

+0

Я повторил ваш ответ немного в моем «ответе» ниже ... хотя мне нужно выяснить, какая версия лучше в контексте исходного вопроса (помощника). –

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 смешивает константу Into Foo для удобства собственных методов Foo в. Для этого шаблона не требуется работать.

+0

Ruby знает, что они являются константами по их делу, или это просто конвенция? –

+0

@yar, Ruby знает, что мы определяем константу, потому что идентификатор начинается с заглавной буквы. Как он отслеживает то, что является постоянным, а что нет, я не знаю. –

+0

Это ироничный печальный факт о Ruby: так много написано в не-Ruby, что трудно узнать все это, если вы не хотите попасть в C ниже. Спасибо за Ваш ответ. –

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 

Я уверен, что я мог бы получить код туже (если бы я знал, как).

+0

Patching Object не имеет смысла, так как это будет работать только на объекте, который имеет по крайней мере каждый метод (так что по крайней мере Enumerable). Также обратите внимание, что если все, что вам нужно, это хэш, где вы можете получить значение для ключа, выполнив 'hash.key' вместо' hash [key] ', вы можете просто использовать OpenStruct (или monkey-patch Hash с' method_missing'). – sepp2k

+0

Спасибо @ sepp2k, я реализовал метод method_missing, но я не знаю, как элегантно обрабатывать ключи как символы ИЛИ строки. –

2

На самом деле рубин имеет что-то под названием OpenStruct, что является довольно удивительным и очень полезным, когда вы хотите хеш, но не хотите использовать его как один.

require 'ostruct' 

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

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

Спасибо, vava, я узнал об этом вчера благодаря комментарию sepp2k моего ответа (ниже где-то). –

Смежные вопросы