How do I use the "define_method" correctly in Ruby?

Asked

Viewed 49 times

1

I was researching on the internet how to create methods dynamically in Ruby and in some forums in English, people spoke to use the method define_method, passing a name to the method and a &block which would be the body of this method. I tried to do this but it does not create the method for me.

See the code below:

class Cachorro

    define_method :falar do
        puts "Au au!"
    end

    def method_missing(method_name,*args)

        if method_name == :andar
            define_method :andar do
                puts "Andando..."
            end
        end

    end
end

animal = Cachorro.new
animal.falar
animal.andar

In this code, the method falar but the andar no. Why does this happen ? What is the right way to use the method define_method ?

And taking advantage of the fact that I’m talking about dynamically creating methods in Ruby, there’s some way to dynamically create attributes like this: animal.nome = 'Bidu' ?

1 answer

2


The method define_method that you used to create the method :falar is a class method. The class method animal.falar that you call is an instance method (the object animal is an instance of the class Cachorro).

So that the creation of the method :andar function properly, you need to execute the class method. For this, you just change define_method for Cachorro.define_method or self.class.define_method, so the method will be created correctly.

However, it will not run soon after its creation, you would need to execute the method :andar twice, one to create and the other with the method already existing. Follow an example of code where the method will be created and executed soon after:

class Cachorro

  define_method :falar do
    puts "Au au!"
  end

  def method_missing(method_name,*args)
    if method_name == :andar
      self.class.define_method :andar do # self.class
        puts "Andando..."
      end
      self.andar # executa logo após a criação
    end

  end
end

animal = Cachorro.new
animal.falar
animal.andar


For attributes dynamically you can use the instance_eval. For example, we can create the attribute nome dynamically with the code below:

class Cachorro

  define_method :falar do
    puts "Au au!"
  end

  def method_missing(method_name,*args)
    if method_name == :andar
      self.class.define_method :andar do # self.class
        puts "Andando..."
      end
      self.andar # define e executa
    else
      self.class.instance_eval do
        attr_accessor method_name
      end
    end
  end
end

animal = Cachorro.new
animal.falar
animal.andar
animal.nome
animal.nome = 'buddy'
puts animal.nome
  • Finally someone answered me kkk. Thank you, it helped a lot!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.