Подтвердить что ты не робот

Динамически определенные методы настройки с использованием 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

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

4b9b3361

Ответ 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