What's the difference between creating a method and a block in a Ruby class?

2

I have the habit of creating methods this way in Ruby:

class MinhaClasse

  def metodo
    # meu método
  end

end

But sometimes found around the direct creation of a block of code in the class:

class MinhaClasse

  bloco do
    # meu bloco
  end

end

What's the use? What is the difference between this and the creation of a method? When and why should it be used?

    
asked by anonymous 11.06.2014 / 15:58

1 answer

3
class MinhaClasse
  def metodo
    # meu método
  end
end

What is happening here is quite simple: You are creating an instance method in the MinhaClasse class. Nothing unusual.

class MinhaClasse
  outro_metodo
end

Already when you write this, you are calling the outro_metodo method on the self object of the context. In this case, the self within the scope of the class is the class itself. This is equivalent to doing MinhaClasse.outro_metodo .

This method could have been defined like this:

def MinhaClasse.outro_metodo
  # código
end

Or so, equivalently:

class MinhaClasse
  def self.outro_metodo
    # código
  end
end

Of course, like any other method invocation, you can pass a block, and the implementation can do whatever you want with the block, including defining an instance method using the block passed as the implementation of it. Something like this:

class MinhaClasse
  def self.criar_metodo(&bloco)
    define_method(:metodo, &bloco)
  end

  criar_metodo do
    puts "oi!"
  end
end

obj = MinhaClasse.new
obj.metodo #=> "oi!"

Here I used define_method , which is a method of class Class to define methods from a block. One can even argue that def metodo(a, b) ... end is a mere syntactic sugar for define_method(:metodo) do |a, b| ... end .

As for use, metaprogramming! This allows you to create syntaxes with "special" behavior, and make the language behave as you want. For example:

class MyButton < Button
  on :click do
    puts "Me clicou!"
  end
end

That could be implemented as:

def Button.on(event, &handler)
  @@callbacks ||= {}
  @@callbacks[event] ||= []
  @@callbacks[event] << handler
end

Or even:

def Button.on(event, &handler)
  define_method("on_" + event, &handler)
end
    
11.06.2014 / 16:22