2010-03-23 1 views
13

Я использую много итераций, чтобы определить удобные методы в моей модели, такие вещи, как:Динамически определенные методы сеттера с использованием define_method?

PET_NAMES.each do |pn| 
define_method(pn) do 
... 
... 
end 

, но я никогда не был в состоянии динамически определять методы сеттер, т.е.:

def pet_name=(name) 
... 
end 

с использованием define_method например:

define_method("pet_name=(name)") do 
... 
end 

Любые идеи? Заранее спасибо.

ответ

37

Вот довольно полный пример использования define_method в модуле, который вы используете, чтобы расширить класс:

module VerboseSetter 
    def make_verbose_setter(*names) 
    names.each do |name| 
     define_method("#{name}=") do |val| 
     puts "@#{name} was set to #{val}" 
     instance_variable_set("@#{name}", val) 
     end 
    end 
    end 
end 

class Foo 
    extend VerboseSetter 

    make_verbose_setter :bar, :quux 
end 

f = Foo.new 
f.bar = 5 
f.quux = 10 

Выход:

 
@bar was set to 5 
@quux was set to 10 

Вы были близки, но вы не хотите включите аргумент метода внутри аргументов вашего звоните в define_method. Аргументы идут в блоке, который вы переходите на define_method.

1

Shoertly, если вам это нужно в один класс/модуля: Я использую хэш, но вы можете поместить там массив элементов и т.д.

PETS = { 
    "cat" => "meyow", 
    "cow" => "moo", 
    "dog" => "ruff" 
} 

def do_smth1(v) 
... 
end 

def do_smth(sound,v) 
... 
end 

#getter 
PETS.each{ |k,v| define_method(k){ do_smth1(v) } } 

#setter 
PETS.each{ |k,v| define_method("#{k}="){|sound| do_smth2(sound, v) }