user2012677
user2012677

Reputation: 5745

NoMethodError: undefined method `define_instance_method'

I am trying to define an instance method on Foo, how do I do that, I keep getting method undefined errors for define_method and define_instance_method? Also, why would I use define_method vs define_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

Upvotes: 1

Views: 1520

Answers (2)

fphilipe
fphilipe

Reputation: 10054

There's Module#define_method and there's Object#define_singleton_method. There is no #define_instance_method.

Module#define_method allows you to define an instance method on the receiving module or class, which is analogous to a def:

class A
  def foo
    123
  end
end

A.define_method(:bar) { 456 }

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

You cannot use it on other type of objects, such as instances of A, which are of type A, only on Module or Class:

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

Object#define_singleton_method, on the other hand, can be used on any Object, including Class and Module. It allows you to create a method on the receiver. For a class or module, that's equivalent to defining a class method:

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'

But we can also use it directly on an instance of a class to add a method to that very instance:

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)

Upvotes: 3

Ritesh Ranjan
Ritesh Ranjan

Reputation: 1012

Module#define_method is a private method and also a class method.Your one didn't work,as you tried to call it on the instance of foo class.You have to call it like this:

class Foo

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

end

Upvotes: 0

Related Questions