我可以在rails模型中使用define_method吗?
我的rails模型的代码试图在模型中使用define_method(method_name)
。
我一直在:
NoMethodError: undefined method `define_method'
我究竟做错了什么? 我是在错误的地方做这件事吗 我需要附加到此模型的此方法。 我还能在哪里定义这种方法?
编辑:对于那些要求查看代码的人:
for field in rdev_fields next if self.attributes.include?(field) count = count + 1 rdev_hash[field.to_sym] = self.attributes["attribute#{count}"] if !self.respond_to?(field) then define_method("#{field}") do self.send("attribute#{count}".to_sym) end end end
没有什么神奇的或关于rails模型,它只是一个普通的类,有一堆预先存在的方法,
所以,问题是“我可以在课堂上定义方法吗?”
第1部分:是的,你可以。
重要的区别在于您可以在类中定义方法而不是在实例方法中
例如:
class Cow define_method "speak" do "MOOOO" end end Cow.new.speak => "MOOOO"
这应该工作正常。 请注意,您在类Cow上定义它,因此您已经拥有的任何其他Cows将自动添加该方法。
第2部分:如果要在实例方法中定义方法,您会怎么做?
您无法从实例方法定义方法,因此您必须获取类,并使用它来定义方法。 像这样:
class Cow def add_speak self.class.send(:define_method, :speak) do "MOOOO added" end end end Cow.new.speak NoMethodError: undefined method 'speak' for # Cow.new.add_speak Cow.new.speak => "MOOOO added"
问题解决了。 精明的读者会注意到,在这个例子中我使用send(:define_method)
– 这是必需的,因为define_method
是私有的,私有方法只能访问它们所在的东西。在这种情况下, define_method
在类中,我们在实例中,所以我们无法直接访问它。
如上所述,我们将该方法直接添加到类中,因此已经存在的所有其他Cows也将自动添加speak方法。
第3部分:如果要仅为1个对象定义方法,而不是该类的所有对象,您会怎么做?
例:
class Cow def add_speak_just_me class << self define_method "speak" do "MOOOO added for just me" end end end end Cow.new.speak NoMethodError: undefined method 'speak' for # c = Cow.new c.add_speak_just_me c.speak => "MOOOO added for just me" # it works, hooray Cow.new.speak # this new cow doesn't have the method, it hasn't been automatically added NoMethodError: undefined method `speak' for #
这是如何运作的? 你去了rabbithole!
阅读本文: http : //dannytatom.me/metaid/祝你好运。 当你意识到“向一个实例添加一个方法”实际上根本没有将它添加到实例时它会有所帮助:-)
能够拼凑这个。 虽然很少了解实际发生的事情。
我的实例方法foo打开类并在其上定义条,以便我可以在我的实例上调用它。 更有经验的人会告诉我们这是否同时打开了一堆蠕虫。
尽管知道你的具体用途会很有用。
class User < ActiveRecord::Base def foo (class << self; self; end).class_eval do define_method(:bar) {puts "bar"} end end end u = User.first u.foo u.bar #=> "bar"
如果您来到这里寻找如何动态定义CLASS方法,因为define_method
不起作用(因为它定义了INSTANCE方法),这是您的答案:
使用define_singleton_method
🙂
你的问题的答案是“是的,你可以”。 至于为什么它不适合你 – 如果你没有为代码提供一些上下文,就不可能肯定地说出原因。