Динамически определенные методы настройки с использованием define_method?
Я использую много итераций, чтобы определить удобные методы в моих моделях, например:
PET_NAMES.each do |pn|
define_method(pn) do
...
...
end
но я никогда не мог динамически определять методы setter, т.е.
def pet_name=(name)
...
end
используя define_method, например:
define_method("pet_name=(name)") do
...
end
Любые идеи? Спасибо заранее.
Ответы
Ответ 1
Вот довольно полный пример использования 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
.
Ответ 2
Если вам нужно это внутри одного класса/модуля:
Я использую хеш, но вы можете поместить туда массив элементов и т.д.
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) }
Ответ 3
Вы можете сделать следующим образом,
%w(xyz1 xyz2 xyz3 xyz4).each do |method_name|
define_method("#{method_name}=") do |value|
value = value.reject(&:empty?).join(";") if value.is_a?(Array)
instance_variable_set("@#{method_name}", value)
end
end