Nesta aula iremos aprender como criar métodos de forma dinâmica, iremos ver os comandos, lambda, Proc.new, eval, instance_variable_get, instance_variable_set, &bloco e iremos criar um modulo para definir atributos de forma dinâmica.

Metaprogramming - Dinâmicos


Lambda

Exemplo básico de lambda.

        
          a = lambda do |p|
            puts p
          end
          a.call("danilo")
        
      

Assim definimos um bloco que pode receber parâmetros e exibe algo na tela, neste caso ele foi atribuído a variavel a, e chamado com o call, e passando um parâmetro, ao chama-lô com a.call("danlo"), é retornado na tela o parâmetro passado.

Proc

Exemplo básico de proc.

        
          a = proc.new do |p|
            puts p
          end
          a.call("danilo")
        
      

Este código terá o mesmo efeito do lambda, mas na passagem de parâmetros ele permite passar vários ou nenhum, enquanto que no lambda ele obriga a passagem de parâmetros.

Bloco de métodos

Exemplo básico de bloco, quando utilizamos o &bloco, ele utiliza o proc ao invés do lambda.

        
          a = proc.new do |p|
            puts p
          end
          a.call("danilo")
        
      
Eval

Exemplo de eval, com ele podemos utilizar um código que seja válido(exacutável).

        
         eval("puts '123'")
        
      

Aula Prática

Como de praxe copie os arquivos das aulas anteriores para seguir conforme o padrão.


Começaremos a ver o lambda padrão.

        
          require 'byebug'

          l = lambda {|param| param * 5}
          puts l.call(4)
          
          l = lambda do |p1, p2| 
            p1 + p2
          end
          puts l.call(4, 5)
          debugger
        
      

O código abaixo gera um erro conforme foi explicado o lambda padrão é necessário passar e referenciar.

        
          require 'byebug'
          
          l = lambda {|param| param * 5}
          puts l.call(4)
          
          l = lambda do |p1, p2| 
            p1 + p2
          end
          puts l.call(4)
          debugger
        
      

Agora com o Proc.new, assim não se torna necessário passar todos parâmetros.

        
          require 'byebug'
          
          l = Proc.new do |param, p2, p3|
            puts param
            puts p2
            puts p3
          end
          
          l.call(4)

          debugger
        
      

Arquivo final:

      
        require 'byebug'

        #lambda não aceita mais parâmetros do que os definidos
        #lambda retorno dentro do proprio lambda
        l = lambda {|param| param * 5}
        puts l.call(4)
        
        l = lambda do |p1, p2| 
          p1 + p2
        end
        puts l.call(4, 5)
        
        
        # puts "ini"
        # def method
        #   puts "indi"
        #   l = lambda {return "s"}
        #   puts l.call
        #   puts "inei"
        # end
        # method
        # puts "fim"
        
        ########################################################
        #lambda aceita mais parâmetros do que os definidos
        #lambda retorno do metodo inteiro
        
        l = Proc.new do |param, p2, p3|
          puts param
          puts p2
          puts p3
        end
        
        l.call(4)
        
        
        
        # puts "ini"
        # def method
        #   puts "indi"
        #   l = Proc.new {return "dd"}
        #   puts l.call
        #   puts "inei"
        # end
        # method
        # puts "fim"
        
        ########################################################
        
        def metodo_para_definir_bloco(&bloco)
          bloco
        end
        
        l = metodo_para_definir_bloco do |param| 
          param * 5
        end
        
        
        puts l.call(4)
        
        l = metodo_para_definir_bloco do 
          puts "danilo"
        end
        
        # debugger
        
        l.call
        
        # debugger
        
        ########################################################
        # convert string na linguagem
        eval "puts 'danilo'"
        ########################################################
        
        atr = "danilo"
        
        eval("
          def #{atr}(value)
            @#{atr} = value
          end
        ")
        
        eval("
          def mostra
            @#{atr}
          end
        ")
        
        danilo('dssds')
        mostra
        
        
        ########################################################
        
        #definindo metodos dinamicos
        
        class Teste
          def inicio
            def fim
            end
          end
        end
        
        t = Teste.new
        # t.fim
        t.inicio
        t.fim
        
        ########################################################
        
        class Teste
          def self.definir(valor)
            define_method(valor) do |param1, param2|
              puts "#{param1} - #{param2}"
            end
          end
        
          def self.atributo(valor)
            define_method(valor) do |param1|
              puts param1
            end
          end
        end
        
        ['set_nome', 'set_telefone', 'set_endereco'].each do |atr|
          Teste.atributo(atr)
        end
        
        teste = Teste.new
        
        
        # Teste.new.novo_metodo('danilo', 'que legal')
        
        ########################################################
        module AtributosDinamicos
          def atributos(*atrs)
            atrs.each do |atr|
              define_method("#{atr}=") do |value|
                instance_variable_set "@#{atr}", value
              end
        
              define_method("#{atr}") do
                instance_variable_get "@#{atr}"
              end
            end
          end
        
          def atributos_somente_leitura(*atrs)
            atrs.each do |atr|
              define_method("#{atr}") do
                instance_variable_get "@#{atr}"
              end
            end
          end
        end
        
        class Teste
          extend AtributosDinamicos
          atributos :nome, :telefone, :cpf
          # atributos_somente_leitura :nome, :telefone, :cpf
          # attr_accessor :nome, :telefone
        end
        
        t = Teste.new
        # debugger
        t.nome = "danilo"
        t.telefone = "3334343"
        
        
        puts "#{t.nome}, #{t.telefone}"
        
        
        # debugger
        
        
        
        x = ""
      
    




Próximas Aulas


Metaprogramming - Eval para Classes e instâncias

Nesta aula iremos aprender como abrir uma classe, com os comandos instance_eval e class_eval é possí...

Metaprogramming - Classes e métodos dinâmicos

Nesta aula iremos aprender como definir classes e métodos em runtime, veremos onde podemos utilizar ...

Metaprogramming - Alias para métodos e atributos

Nesta aula iremos aprender a renomear ou duplicar métodos de forma dinâmica utilizando o comando ali...

Metaprogramming - Hooks

Nesta aula iremos aprender os conceitos de hooks, veremos como utilizar 3 tipos de hooks (web hook, ...

Metaprogramming - Missings

Nesta aula iremos aprender a utilizar os comandos const_missing e method_missing, com isso iremos cr...

Instalando Rails

Nesta aula iremos aprender a instalar e configurar o Rails que é um dos frameworks mais utilizados p...

Rails Generators

Nesta aula iremos aprender um pouco sobre os generators do Rails, utilizaremos o, scaffold, models e...

Rails - Routes

Nessa aula iremos iniciar uma aplicação web do zero, agora passo a passo. Iremos ver algumas rotas u...



Danilo

Arquiteto de software, analista, programador, professor. Danilo criou o projeto torne-se um programador, para passar o seu conhecimento para a nova geração. Com o intuito de ser um bom pai, Danilo trabalha muito motivado para garantir o futuro de sua filha.

ELEVE SEUS GANHOS E POTENCIALIZE SUA PERFORMANCE

Receba nossa Ebook de LÓGICA DE PROGRAMAÇÃO

© Didox Business & Technology - CNPJ: 12.127.195/0001-14