MouseOver Studio

MouseOver Studio header image 2

Anotações em Ruby

maio 1st, 2010 por Diego Carrion · 2 comentários

Na mundo da programação, uma anotação é um jeito de marcar o código que esta embaixo dele para diversos fins. No Cucumber, as tags que ele utiliza são uma espécie de anotação para poder aplicar callbacks e classificar algumas funcionalidades e cenários:

@billing
Feature: Verify billing

  @important
  Scenario: Missing product description

  Scenario: Several products

No caso do VRaptor temos anotações para poder classificar um controller como recurso REST ou especificar o acesso a uma action:

@Resource
public class ShoppingCartController {
    ...
}

public class ProductsController {
    @Post
    @Path("/products")
    public void add(Product product) {...}
    ...  
}

Em Ruby, duas anotações que utilizamos bastante são os métodos private e protected, que sem argumentos restringem a visibilidade dos métodos definidos embaixo deles:

class User
  def jump; end;

  protected
  def eat; end;
  def flirt; end;

  private
  def sleep; end;
  def dream; end;
end

Dependendo do caso, podemos querer anotar nosso código nesse estilo, como por exemplo para especificar que um método esta depreciado, funcionalidade que podemos obter com a gem Canivete do Douglas Campos:

class Bomb
  deprecate
  def explode; end
end

No código acima, quando alguém chamar o método Bomb#explode, o interpretador ira efetivamente executar o método, mas além disso ira imprimir: Warning: calling deprecated method Bomb.explode.

Esse comportamento pode ser obtido por causa do método method_added, presente em todos os módulos do Ruby, que é chamado toda vez que um método e definido, recebendo o nome do mesmo como parâmetro.

Podemos utilizar esse método então por exemplo para criar uma anotação que serva para especificar que os métodos declarados após ela somente podem ser chamados por um admin, algo assim:

class Module
  def method_added(name)
    unless @_admin_only.nil? or @_proxy_method
      @_proxy_method = true
      alias_method "_admin_#{name}", name
      module_eval <<-STRING
        def #{name}(*args, &block)
          _admin_#{name}(*args, &block) if admin?
        end
      STRING
      @_proxy_method = false
    end
  end

  def admin_only
    @_admin_only = true
  end
end

class User
  def admin?
    [true, false][rand(2)]
  end

  admin_only

  def update_password
    puts "password updated"
  end

  def restart_server
    puts "server restarted"
  end
end

Nó código acima, #admin? ira devolver verdadeiro ou falso aleatoriamente e dependendo do resultado, o método chamado ira ser executado ou não.

Tags: Annotations · cucumber · Meta Programming · ruby · vraptor

2 respostas ate agora ↓

  • 1 Lucas // mai 1, 2010 at 9:58 pm

    Ótimo post e gem muito interessante. Este tipo de código só reforça as coisas elegantes que podem ser feitas com ruby.

  • 2 André // set 15, 2010 at 3:17 pm

    Excelente post.

Deixar um comentário