使用define_method动态定义的setter方法?

时间:2010-03-23 10:55:10

标签: ruby-on-rails ruby activerecord metaprogramming

我使用了很多迭代来定义模型中的便捷方法,例如:

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

有什么想法吗?提前谢谢。

2 个答案:

答案 0 :(得分:38)

以下是在您用于扩展课程的模块中使用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 :(得分:1)

如果你需要在一个课程/模块中,那就太过分了: 我使用哈希,但你可以放置元素数组等。

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) }