NoMethodError:未定义的方法`define_instance_method'

时间:2019-08-30 12:13:13

标签: ruby-on-rails ruby ruby-on-rails-5.2

我正在尝试在Foo上定义一个实例方法,该怎么做,我不断使define_method和define_instance_method的方法未定义错误? 另外,为什么我要使用define_methoddefine_instance_method

class Foo
  def boo
    self.instance_variable_set('@a', "help")  # => "help"
  end                                         # => :boo

  def voo
     self.instance_variable_get('@a')  # => "help"
  end                                  # => :voo

 def noo
   define_method 'goo' do  # ~> NoMethodError: undefined method `define_method' for #<Foo:0x00007fce1309e000 @a="help">\nDid you mean?  define_singleton_method
     "goo"
   end
 end                       # => :noo

 def woo
   define_instance_method 'qoo' do  # ~> NoMethodError: undefined method `define_instance_method' for #<Foo:0x00007feacb98e780 @a="help">\nDid you mean?  define_singleton_method
     "qoo"
   end
 end                                # => :woo

end  # => :woo

2 个答案:

答案 0 :(得分:1)

Module#define_methodObject#define_singleton_method。没有#define_instance_method

Module#define_method允许您在接收模块或类上定义实例方法,类似于def

class A
  def foo
    123
  end
end

A.define_method(:bar) { 456 }

A.new.foo # => 123
A.new.bar # => 456

您不能在AA上的其他类型的对象上使用它,例如Module的实例,这些实例的类型为Class

A.new.define_method(:bogus) { 'oops' }
# => NoMethodError (undefined method `define_method' for #<A:0x00007ffa6c0c77e0>)
另一方面,

Object#define_singleton_method可以用于任何Object,包括ClassModule。它允许您在接收方上创建一个方法。对于一个类或模块,这等效于定义一个类方法:

class B
  def self.x
    'x'
  end

  class << self
    def y
      'y'
    end
  end
end

B.define_singleton_method(:z) { 'z' }

B.x # => 'x'
B.y # => 'y'
B.z # => 'z'

但是我们也可以直接在类的实例上使用它,以向该实例添加方法:

class C; end
c = C.new
c.define_singleton_method(:foo) { 'hello' }
c.foo # => 'hello'
C.new.foo # => NoMethodError (undefined method `foo' for #<C:0x00007ff95f0e4038>)
C.foo # => NoMethodError (undefined method `foo' for C:Class)

答案 1 :(得分:0)

Module#define_method是一个私有方法,也是一个类方法。您试图在foo类的实例上调用它时,您的那个方法没有用。您必须像这样调用它:

class Foo

 def noo
   self.class.send(:define_method,'goo') { puts 'Goo'}
 end

end