Entendendo Rails
Fabio Akita
Surgeworks Brazil Rails Practice Manager
www.akitaonrails.com
37signals
• Criado por David Heinemeier Hansson,
em 2004
• Extraído do aplicativo Basecamp
• Feito em Ruby, em vez de PHP ou Java
• Lançamento da versão 1.0 em dez/2005
O que é Rails?
• “full stack web framework”
• Framework completo para desenvolvimento de aplicativo
Web
• Pacote MVC (Model-View-Controller)
– Action Pack (Action Controller e Action View)
– Active Record
• Suporte a envio e recebimento de e-mails
– Action Mailer
• Suporte a Web Services
– Action WebServices
Arquitetura Rails
Por que Ruby?
•
•
•
•
•
•
•
•
•
Linguagem Dinâmica
Fortemente Tipada
Muito Expressiva
Altamente Produtiva
Totalmente Orientado a Objetos
Herança de SmallTalk e Lisp
Simples sem ser complexa
Sintaxe familiar e coerente
Permite criação de Linguagem Específica
de Domínio (DSL)
Começo Simples
• Windows: Instant Rails
– wiki.rubyonrails.com/rails/pages/InstantRails
• Mac e Linux:
– FiveRuns RB-Install
• www.fiveruns.com/products/rm/install
Começo Padrão
• Instalar Ruby 1.8.6
– www.ruby-lang.org/en/downloads
• Instalar RubyGems (Mac ou Linux)
– rubyforge.org/frs/?group_id=126
• Instalar Rails (linha de comando)
– gem install rails
• Instalar MySQL (suporta outros bancos)
– dev.mysql.com/downloads
Primeiro Passo
• Saber o que queremos:
– David Hansson tem um screencast
demonstrando a criação de um pequeno blog
em 15 minutos
–
http://media.rubyonrails.org/video/rails_take2_with_sound.mov
• Queremos um blog semelhante
O Que temos no Blog?
•
•
•
•
•
•
Uma tabela de Posts
Uma tabela associada de Comments
Uma tela de listagem de Posts
Uma tela de criação e edição de Posts
Uma tela de detalhes do Post
No detalhe do Post vemos e adicionamos
Comments
• Faremos tudo em inglês. Não é difícil adaptar
para Português, mas não é escopo desta
demonstração
Novo Projeto
• rails <projeto>
Novo Banco de Dados
• create database <projeto>_<ambiente>
Ambientes
• Rails vem preparado para lidar com três
ambientes diferentes:
– Development (sandbox)
– Test (testes unitários, funcionais, integrados)
– Production (produção)
Convenção sobre Configuração
• Estrutura comum de diretórios
Configuração Mínima
• Banco de dados
• No exemplo, apenas colocando as senhas
Criando um Controller
• script/generate controller <nome>
Controllers e Actions
• Todo Controller fica no diretório:
– /app/controllers/<nome>_controller.rb
• Todo Controller herda a classe
ApplicationController
• Todo aplicativo Rails é criado com uma classe
chamada ApplicationController, que herda de
ActionController::Base, e é base de todos os
outros controllers
• Todo método de um controller é chamado de
Action
Criando uma Action
• Uma classe Controller pode ter quantas
Actions quanto necessárias
Servidor de Teste: WEBRick
Roteamento Customizável
• http://localhost:3000/:controller/:action/:id
Acessando uma Action
• Seguindo a regra anterior de roteamento
– http://localhost:3000/blog/index
– blog = app/controller/blog_controller.rb
– index = método index em BlogController
Criando uma View
Mais Convenções
• Ao final de toda Action, Rails chamará uma view
com o mesmo nome da Action, no seguinte
diretório:
– /app/views/<controller>/<action>.<ext>
• A extensão do arquivo pode ser:
– .rhtml - Embedded Ruby (HTML+Ruby)
– .rxml - XML Builder (Ruby puro)
– .rjs - Javascript Generator (Ruby puro)
• Este fluxo pode ser interrompido com uma
chamada explícita ao método render ou
redirect_to
Implementando Post
• script/generate model <nome>
Migration
• Manutenção de tabelas usando Ruby
• Independente de banco
• Mas também suporta SQL nativo
Rake: Ruby Make
• Execução de tarefas, implementadas em Ruby
• Primeira tarefa: manutenção das tabelas
rake migrate
• Toda entidade criada com script/generate gera um
arquivo de Migration no diretório db/migrate
• Todo arquivo Migration é numerado:
– 001_create_posts.rb
• O comando rake migrate executa os arquivos em
db/migrate
• Usa a tabela schema_info no banco de dados para saber
a partir de qual numeração começar
• O gerenciamento do banco de dados é feito totalmente
em Ruby
Mapeando Tabelas
•
A classe Post já é capaz de gerenciar os dados da tabela no banco de dados
•
Não há necessidade de explicitar o mapeamento das colunas do banco com
atributos da classe
•
Rails não proíbe nada: se for necessário existe como mapear uma coluna para
outro atributo de nome diferente
Convenções de Entidades
• Toda entidade é criada no diretório padrão:
– /app/models/<controller>/<model>.rb
• Toda entidade herda diretamente da classe
ActiveRecord::Base
• Não há necessidade de mapear manualmente cada coluna
da tabela
• Convenção: a classe tem o nome no singular (Post), a
tabela tem o nome do plural (posts)
• Convenção: Surrogate Key, toda tabela tem uma chave
primária chamada “id” que é um número autoincrementável
annotate_models
annotate_models
• Plugin de Dave Thomas
• Instalação (via internet):
– script/plugin install annotate_models
• Utilização (via rake):
– rake annotate_models
• Lê a tabela do banco de dados e coloca
um cabeçalho como comentário na classe
entidade
Scaffold
Scaffold
• Colocar o método scaffold :<model> no
controller é suficiente
• Telas CRUD (Create, Read, Update,
Delete) geradas automaticamente em
tempo de execução (runtime)
• CUIDADO: Rails NÃO é Scaffold
• Scaffold é apenas uma pequena
funcionalidade para facilitar prototipação
Configurando Post
• Acrescentando validação
Testando modificação
• Não é necessário reiniciar servidor
Incrementando Post
• Criando novas colunas com Migration
• script/generate migration <atividade>
Executando Migration
Criando um Post
• Novamente, sem reiniciar o servidor
Gerando o Scaffold
• script/generate scaffold <model> <controller>
Arquivos Gerados
• Toda execução automática de antes agora está exposta
em arquivos que podemos editar como quisermos
• Provado: Rails não se restringe a Scaffold automático
Modificando a Listagem
• /app/views/blog/list.rhtml
Testando a listagem
• http://localhost:3000/blog
• Portanto, podemos alterar o layout ou
qualquer código como quisermos
Polêmica do Scriplet
• Rails não utiliza taglibs
• Ruby é simples e expressiva o suficiente
para não precisar de artifícios
• Taglibs são simplificações de lógica
• Podemos fazer tudo de maneira simples
e flexível sem precisar aprender sintaxes
complexas de XML
Exemplos
Taglibs
Scriptlets
<logic:iterate id=”post"
collection="<%=posts%>">
<% @posts.each do |post| %>
Faz alguma coisa com post
<% end %>
Faz alguma coisa com post
</logic:iterate>
<logic:equal parameter="number"
value="7">
<% if number == "7" %>
Está correto!
<% end %>
Está correto!
</logic:equal>
Portanto, é a mesma coisa !
Criar Comment
• Hora de criar a entidade Comment
• Lembrete: esta entidade será associada a um Post
Rake outra vez
•
Obs: Comment pertence a Post através da coluna post_id.
•
Convenção de Chave Estrangeira: <classe>_id
Associações
Usando associações
• Criando formulário de Comment na tela de detalhe de um
Post
– /app/views/blog/show.rhtml
Partials
• “Don’t Repeat Yourself” (DRY)
• Uma das maneiras de separar trechos de código
• Toda partial começa com underline “_”
– <%= render :partial => "comment", :collection =>
@post.comments %>
• Associação has_many em Post automaticamente fornece um
hash chamado comments (nome da outra entidade no plural)
Action para Comment
•
<% form_for :comment, @comment, :url => {:action => 'add_comment', :id =>
@post } do |f| %>
–
Action esperada: add_comment
–
Passando parâmetros: params[:id] e params[:comment]
–
Hash params[:comment] contém todos os campos do formulário enviado.
Resultado Final
• Tela de Post com a lista de Comments
Layouts
•
Todo novo controller automaticamente ganha um layout no diretório:
– /app/views/layouts/<controller>.rhtml
– As views desse controller preenchem o espaço:
• <%= @content_for_layout %>
Testes Unitários
• Toda nova entidade ganha um arquivo para teste unitário em:
– /app/test/unit/<entidade>_test.rb
• Devemos seguir os preceitos de Test-Driven Development:
– “Se não vale a pena testar, para que estamos codificando?”
Ambiente de Teste
• Os testes acontecem em banco de dados
separado do desenvolvimento
– <projeto>_test
• Cada teste roda de maneira isolada: os
dados modificados em um teste não
afetam outro teste
• Cada teste unitário tem um arquivo de
“fixture”, carga de dados para testes:
– /app/test/fixture/<tabela>.yml
Fixture YAML
• “YAML Ain’t a Markup Language”
• Maneira de serializar objetos Ruby em forma de texto
• Formato humanamente legível
• Mais leve e simples que XML
Rodando Testes Unitários
• Todos os testes unitários
– rake test:units
• Apenas um teste unitário:
– ruby test/unit/<entidade>_test.rb
Testes Funcionais
•
Todo novo controller ganha uma classe de teste em:
– /app/test/functional/<classe>_controller_test.rb
•
Devemos testar cada action do controller
•
Métodos como get e post simulam navegação com um browser
Rodando Testes Funcionais
• Todos os testes funcionais:
– rake test:functionals
• Apenas um testes funcional:
– ruby test/functional/<classe>_controller_test.rb
Mais Testes
• Testes Unitários devem testar todos os aspectos
da entidade como associações, validações,
callbacks, etc
• Testes Funcionais devem testar todas as actions
de um mesmo controller, todos os fluxos,
redirecionamentos, filtros, etc
• Testes Integrados servem para avaliar a
navegação e fluxos entre actions de diferentes
controllers. Funcionam de maneira semelhante
a um teste funcional
Ajax
• Rails é o melhor modelo de framework para
Ajax
• Ajax é codificado em Ruby puro
• Integração com as bibliotecas Prototype e
Script.aculo.us
• Ajax representa um passo em direção a um
“Aplicativo” Web
– Sem necessidade de recarregar a página toda a cada
ação
– Capacidade de atualizar apenas trechos da tela
– Capacidade de realizar um post (submit) sem sair da
página
– Capacidade de receber apenas a informação que
precisa ser atualizada em vez de receber a página
inteira
View Ajaxfied
• Maneira simples: apenas trocar form_for para
remote_form_for
Action Ajaxfied
•
request.xhr? checa se veio chamada via Ajax. Caso contrário
redireciona para a mesma action de antes, que retorna a página toda
•
Desta vez guardamos o novo comment na variável de instância
@comment
Arma Secreta: RJS
• Mesma convenção: action add_comment espera
encontrar a página
– /app/views/blog/add_comment.rjs
Ativando Ajax
• Ativado por controller, através de seu layout
com o método javascript_include_tag
Testando Ajax
• Na foto de tela não podemos mostrar o efeito.
• Recomendamos testar ao vivo. As possibilidades são enormes!
Active Record Interativo
•
script/console
•
Toda entidade criada pode ser manipulada pelo console
•
Facilita testes antes de criar as actions
Produto Final
• Mini Blog criado conforme requerimentos
iniciais (slide 9)
• Plus: pequeno brinde via Ajax
• Conseguimos criar entidades e tabelas sem
mapear campo-a-campo manualmente
– deixe o computador trabalhar por nós
• Infraestrutura completa de testes unitários,
funcionais e integrados
• Obs: este é um aplicativo de demonstração,
muito mais ainda pode ser feito !
O que NÃO fizemos
•
Não precisamos recompilar e reinstalar o aplicativo a cada mudança
•
Não precisamos reiniciar o servidor a cada mudança
•
Não precisamos mapear cada uma das colunas das tabelas para as
entidades
•
Não precisamos configurar dezenas de arquivos XML. Basicamente
colocamos a senha do banco de dados, apenas
•
Não precisamos usar Javascript para fazer Ajax: a maior parte pode ser
feita com Ruby puro
•
Não sentimos falta de taglibs: expressões Ruby, partials foram simples
o suficiente
•
Não precisamos codificar código-cola, o framework possui “padrões
espertos” afinal, todo aplicativo Web tem a mesma infraestrutura
Linhas de Código
• Estatística polêmica mas relevante
• Ruby on Rails permite fazer muito mais com
muito menos
Próximos Passos
• Aprender mais!
– Programming Ruby (livro gratuito! Em inglês)
– http://www.rubycentral.com/book/intro.html
– Agile Web Development With Rails (livro mais famoso
de Rails, em inglês)
– http://www.pragmaticprogrammer.com/titles/rails2/
– Melhores websites sobre Ruby e Rails
– http://del.icio.us/fabioakita/rubyonrails
– Akita On Rails: principal site de Rails do Brasil
– http://www.akitaonrails.com
… e TAMBÉM
• Repensando a Web com Rails
– Primeiro livro de Ruby on Rails em português no Brasil
– Documentação completa do Rails versão 1.1.2
– Cada um dos tópicos desta demonstração em detalhes
– Por Fabio Akita (www.balanceonrails.com.br)
• Consultor SAP há 5 anos
• Gerente de Projetos PMP
• Desenvolvedor Java há 8 anos
• Utilizando diversas plataformas de desenvolvimento há
14 anos
– Pela editora Brasport, já disponível!
Dúvidas
Sugestões
Críticas
• Participe de nosso grupo
– [email protected]
• Podem me escrever diretamente
– [email protected]
Download

Entendendo Rails - s3.amazonaws.com