Ruby - Rails Hildebrando em 04 Set 2008
Ruby On Rails - Dia 3
Na aula anterior finalizamos a aplicação CRUD. Tomou um certo tempo devido a alguns ajustes de configuração e também porque a cada camada alguns conceitos iam sendo discutidos. Hoje o objetivo foi o estudo aprofundado de ActionRecord e ActionController.
ActionRecord
Existem algumas estratégias para fazer o mapeamento objeto-tabela (ORM), no caso do ActiveRecord uma funcionalidade que o difere de outras implementações (como DAO por exemplo) é o fato de a própria entidade possuir métodos de interação com o banco. Isso faz com que se diminua o numero de classes e se reaproveite os atributos do objeto.
Mas isso é so uma parte. Como a estrutura da linguagem Ruby é tão flexível, é possível ter definições de método de consulta no próprio objeto como por exemplo :
User.find_by_username("login")
Inclusive, dizer que o Rails é um framework ORM eu considero meio equivocado, na verdade o Rails não mapeia as colunas para os atributos, ele adiciona nos objetos as colunas. Toda vez que se pede algo para uma classe, o Rails faz um metadados na tabela associada a insere esses atributos dinamicamente no objeto. Assim, se alguem inserir uma nova coluna na tabela, ela automaticamente sera carregada nos objetos.
Isso remete a um outro assunto discutido em sala, Migration.
Migration
Atualizações em tabelas de banco são muitas. Por mais que se faça um trabalho legal de modelagem, invariávelmente temos que criar colunas, refatorar nomes, ajustas associações e por ai vai. Manter essa documentação de atualizações organizada de forma coerente e prática pode demandar uma intereção custoza na equipe de desenvolvimento/banco. Nisso entra o Migration. Com um padrão de nomenclaturas de arquivo e uma facilidade de comandos, é possível versionar os estados das estruturas e trocar facilmente de uma versão para outra. Bem interessante.
Mas isso não tem a ver só com Rails. Isso tem a ver com a organização da manutenção dos dados da empresa. O legal é que como a linguagem utilizada é Ruby e o framework é o Rails, fica muito mais prático, porém poderia ser utilizado para qualquer equipe em qualquer linguagem/plataforma.
Operações Bulk
Operaçoes em massa são aquelas que alteram varios registros ao mesmo tempo, por exemplo :
update users set ativo = 1
Acessível pelos métodos
User.update_all("ativo = 1")
User.destroy_all("ativo = 1")
Eventos - Callbacks
Métodos de callbacks são aqueles invocados quando ocorre determinada situação. No rails eles aparecem nos eventos de interação com o banco. São bem simples de criar e utilizar.
Exemplos :
class User < ActiveRecord::Base
before_destroy :manda_email
def manda_email
#Manda email para alguém
end
end
Outros recursos
Para validações ja tem um monte de funções prontas para serem utilizadas, é possível especializar algumas e criar as suas. Muito útil e fácil.
validates_inclusion_of :age , :in => 15..99
Para os acumuladores (count, sum, minimum, etc) também é bem prático e útil.
User.count(:condition => "age > 18")
Um assunto que discutimos muito (e eu sempre me emociono) é da parte de transações. Como eles conseguiram deixar tão simples.
User.transaction do
a1.deposit(100)
a2.withdraw(100)
end
Se der exceção é feito rollback senão commit. E a funcionalidade não para ai, se você quiser que os objetos retornem ao estado anterior do bloco de transação é so :
User.transaction(a1,a2) do
a1.deposit(100)
a2.withdraw(100)
end
Mais um recurso, facil de implementar, porém muito inteligente são as colunas timestamps, que se seguirem a convenção de nomes funcionam assim :
created_on grava a data/hora ao inserir um novo registro
created_at grava a data ao inserir um novo registro
updated_on grava a data/hora ao atualizar o registro
updated_at grava a data ao atualizar o registro
E por ultimo, um recurso que muita gente nem conhece, Lock otimista (Optimistic Lock). Funciona assim, quando consultamos um registro no banco e abrimos seus dados para edição o registro não fica “lockado” para nosso acesso, ele fica disponível para outros fazerem a mesma operação no mesmo registro. Isso ocorre porque em aplicações com muitos usuarios, se houvesse esse lock todos os outros usuarios ficariam esperando o primeiro finalizar, seria a estratégia pessimista, pois ja pensa que se não segurar o registro outro vai na frente e salva antes. Isso pode acontecer, lógico, mas a estratégia implementada é criar uma coluna de versão.
Quando eu consulto um registro, fica a informação da versão que estou editando, se alguem salvar na minha frente vai atualizar a versão, e quando eu for salvar o ambiente de avisa “Olha, alguem ja salvou antes”.
Implementar isso leva um certo tempo de desenvolvimento, porém em rails é so voce criar uma coluna com o nome lock_version.
Da parte do ActionRecord foi isso vamos ao ActionController
ActionController
Para quem esta acostumado com frameworks web, esse é o controlador de fluxo. Vantagens do framework Rails é a facilidade de criação (não tem XMLs nem anotações, somente convenções) e inclusão de actions (métodos que recebem requisições).
Todo método criado na classe Controller pode receber requisição, e o legal é que existe um diretorio específico para cada pagina de cada controlador. É mais ou menos o que acontece na realidade, um controlador acaba “gerenciando” um grupo de paginas específicas do seu contexto.
O interessante é que acessar a pagina de outro controlador, mudar de pagina para retorno em conteudo texto ou verificar se é uma requisição ajax é facil. É abstraido muitos conceitos da parte de troca de mensagens HTTP.
Exemplos:
Para retornar texto
def teste_texto
s = "Esse é o texto que sera retornado"
render :text => s
end
Para retornar uma pagina do mesmo controller
def teste_uma_pagina
#Faz algumas operacoes
render :action => 'uma_pagina'
end
Para retornar uma pagina com mesmo nome do método
def uma_pagina
#Faz algumas operacoes
end
Para retornar uma página de um outro Controller (adivinham ?)
def teste_mais_complexo
#Faz algumas operacoes
render :controller => 'loja_virtual' , :action => 'outra_pagina'
end
Também existem recursos de verificação, como so deixar executar os métodos que forem por post.
verify :method => :post,
nly => [ :destroy , :create , :update],
:redirect_to => { :action => :list }
Para configurar os layouts utilizados por esse controler, é so adicionar no inicio do corpo da classe :
layout :loja_virtual_usuario
Para configurar filtros de requisição :
before_filter :valida_usuario
def valida_usuario
#faz a validacao
end
Existem outros recursos como flash[:notice] para o envio de mensagens com tempo de vida da requisiçao, outra funcionalidade é o render para montar as paginas de resposta, tem tambem o rescue para lançar excessão e depois trata-la.
Tanto o assunto de ActionRecord quanto de ActionController foram muito bem trabalhados no livro. Vale a pena dar uma conferida.
Amanhã tem mais.
Enviar por e-mail | Hits para esta publicação: 348