Você está na página 1de 71

Entendendo Rails

Fabio Akita www.balanceonrails.com.br

Entendendo Rails Fabio Akita www.balanceonrails.com.br
Entendendo Rails Fabio Akita www.balanceonrails.com.br

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

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: Locomotive

– locomotive.raaum.org

• Linux: Rails Live CD

– www.railslivecd.org

Começo Padrão

• Instalar Ruby 1.8.4

– www.ruby-lang.org/en/20020102.html

• 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 Projeto • rails <projeto>

Novo Banco de Dados

• create database <projeto>_<ambiente>

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

Convenção sobre Configuração • Estrutura comum de diretórios

Configuração Mínima

• Banco de dados

• No exemplo, apenas colocando as senhas

Configuração Mínima • Banco de dados • No exemplo, apenas colocando as senhas

Criando um Controller

• script/generate controller <nome>

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

Criando uma Action • Uma classe Controller pode ter quantas Actions quanto necessárias

Servidor de Teste: WEBRick

Servidor de Teste: WEBRick

Roteamento Customizável

• http://localhost:3000/:controller/:action/:id

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

http://localhost:3000/blog/index – blog = app/controller/blog_controller.rb – index = método index em BlogController

Criando uma View

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>

Implementando Post • script/generate model <nome>

Migration

• Manutenção de tabelas usando Ruby

• Independente de banco

• Mas também suporta SQL nativo

Migration • Manutenção de tabelas usando Ruby • Independente de banco • Mas também suporta SQL

Rake: Ruby Make

• Execução de tarefas, implementadas em Ruby

• Primeira tarefa: manutenção das tabelas

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

classe • Rails não proíbe nada: se for necessário existe como mapear uma coluna para outro

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 auto- incrementável

annotate_models

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

Sca! old

Sca ! old

Sca! old

• 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

Configurando Post • Acrescentando validação

Testando modificação

• Não é necessário reiniciar servidor

Testando modificação • Não é necessário reiniciar servidor

Incrementando Post

• Criando novas colunas com Migration

• script/generate migration <atividade>

Incrementando Post • Criando novas colunas com Migration • script/generate migration <atividade>

Executando Migration

Executando Migration

Criando um Post

• Novamente, sem reiniciar o servidor

Criando um Post • Novamente, sem reiniciar o servidor

Gerando o Sca ! old

• script/generate scaffold <model> <controller>

Gerando o Sca ! old • 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

está exposta em arquivos que podemos editar como quisermos • Provado: Rails não se restringe a

Modificando a Listagem

• /app/views/blog/list.rhtml

Modificando a Listagem • /app/views/blog/list.rhtml

Testando a listagem

• http://localhost:3000/blog

Testando a listagem • http://localhost:3000/blog • Portanto, podemos alterar o layout ou qualquer código como

• 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

Taglibs

Exemplos

Scriptlets

<logic:iterate id=”post" collection="<%=posts%>"> Faz alguma coisa com post </logic:iterate>

<logic:equal parameter="number"

value="7">

Está correto! </logic:equal>

<% @posts.each do |post| %> Faz alguma coisa com post <% end %>

<% if number == "7" %> Está correto! <% end %>

Portanto, é a mesma coisa !

Criar Comment

• Hora de criar a entidade Comment

• Lembrete: esta entidade será associada a um Post

Criar Comment • Hora de criar a entidade Comment • Lembrete: esta entidade será associada a

Rake outra vez

• Obs: Comment pertence a Post através da coluna post_id.

• Convenção de Chave Estrangeira: <classe>_id

vez • Obs: Comment pertence a Post através da coluna post_id. • Convenção de Chave Estrangeira:

Associações

Associações
Associações

Usando associações

• Criando formulário de Comment na tela de detalhe de um Post

– /app/views/blog/show.rhtml

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)

• Associação has_many em Post automaticamente fornece um hash chamado comments (nome da outra entidade no

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.

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

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 %>

– 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?”

seguir os preceitos de Test-Driven Development: – “Se não vale a pena testar, para que estamos

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

• Maneira de serializar objetos Ruby em forma de texto • Formato humanamente legível • Mais

Rodando Testes Unitários

• Todos os testes unitários

– rake test:units

• Apenas um teste unitário:

– ruby test/unit/<entidade>_test.rb

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

• Devemos testar cada action do controller • Métodos como get e post simulam navegação com

Rodando Testes Funcionais

• Todos os testes funcionais:

– rake test:functionals

• Apenas um testes funcional:

– ruby test/functional/<classe>_controller_test.rb

– 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

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

action de antes, que retorna a página toda • Desta vez guardamos o novo comment na

Arma Secreta: RJS

• Mesma convenção: action add_comment espera encontrar a página

– /app/views/blog/add_comment.rjs

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

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!

Ajax • Na foto de tela não podemos mostrar o efeito. • Recomendamos testar ao vivo.

Active Record Interativo

• script/console

• Toda entidade criada pode ser manipulada pelo console

• Facilita testes antes de criar as actions

• script/console • Toda entidade criada pode ser manipulada pelo console • Facilita testes antes de

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

Linhas de Código • Estatística polêmica mas relevante • Ruby on Rails permite fazer muito mais

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

Balance On Rails: principal site de Rails do Brasil

– http://www.balanceonrails.com.br

… e aguarde

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, previsão: durante inverno de 2006

Dúvidas

Sugestões

Críticas

• Participe de nosso grupo

– balanceonrails@googlegroups.com

• Podem me escrever diretamente

– fabioakita@gmail.com