Curso de Ruby on Rails - Aula 03

2.720 visualizações

Publicada em

Material do curso de Ruby on Rails.

Publicada em: Tecnologia
0 comentários
0 gostaram
Estatísticas
Notas
  • Seja o primeiro a comentar

  • Seja a primeira pessoa a gostar disto

Sem downloads
Visualizações
Visualizações totais
2.720
No SlideShare
0
A partir de incorporações
0
Número de incorporações
4
Ações
Compartilhamentos
0
Downloads
96
Comentários
0
Gostaram
0
Incorporações 0
Nenhuma incorporação

Nenhuma nota no slide

Curso de Ruby on Rails - Aula 03

  1. 1. Aprendendo Ruby on Rails - Aula 3 Maurício Linhares
  2. 2. partials – reorganizando as views}  Quando uma view cresce demais ou tem pedaços que podem ser reutilizados em outros lugares, esses pedaços podem ser transformados em um “partial”;}  Partials são arquivos de view onde o nome começa com um “_” (underline) como em “_items.html.erb”;}  É possível passar variáveis para partials e eles também tem acesso a todas as variáveis de instância que estejam nas views; 2
  3. 3. app/views/items/_item.html.erb<tr> <td> <%= item.nome %> </td> <td> <%= item.quantidade %> </td> <td> <%= number_to_currency item.preco_unitario %> </td> <td> <%= number_to_currency item.preco_total %> </td></tr> 3
  4. 4. Fazendo a chamada do partial – app/views/itens/index.html.erb<table> <thead> <tr> <td> Nome </td> <td> Quantidade </td> <td> Preço unitário </td> <td> Preço total </td> </tr> </thead> <tbody> <% pedido_atual.itens.each do |item| %> <%= render item, :item => item %> <% end %> </tbody></table> 4
  5. 5. <%= render ‘ item‘, :item => item %>}  Gere o partial “_item” dentro da pasta da view atual;}  Passe a variável item com o nome “:item” para o partial;}  Quando o caminho completo não for dado, o partial vai ser sempre procurado na pasta de view do controller atual;}  render :partial => “items/item”, :locals => { :item => item } 5
  6. 6. Alterando vários itens ao mesmo tempo nocarrinho – formulários aninhados}  A solução mais simples pra editar vários elementos ao mesmo tempo em uma página;}  Rails tem suporte direto a formulários aninhados dentro do framework;}  Para usar formulários aninhados (para os objetos relacionados a outro) nós utilizamos o helper “accepts_nested_attributes_for”; 6
  7. 7. Na classe Pedidoclass Pedido < ActiveRecord::Base has_many :itens accepts_nested_attributes_for :itens #resto dos métodosend 7
  8. 8. Formulário no carrinho<%= form_tag atualizar_carrinho_itens_path, :method => :post do %> <table> <thead> <tr> <td> Nome </td> <td> Quantidade </td> <td> Preço unitário </td> <td> Preço total </td> </tr> </thead> <tbody> <% pedido_atual.itens.each do |item| %> <%= render item, :item => item %> <% end %> </tbody> </table><% end %> 8
  9. 9. Adicionando campo de formulário ao_item.html.erb<tr> <td><%= item.produto.nome %></td> <td> <%= hidden_field_tag pedido[itens_attributes][][id], item.id%> <%= text_field_tag pedido[itens_attributes][][quantidade],item.quantidade %> </td> <td><%= number_to_currency item.produto.preco %></td> <td><%= number_to_currency item.preco_total %></td></tr> 9
  10. 10. Formato do formulário para itens aninhados}  pedido[itens_attributes][][id]’ }  Cada item deve vir com o seu próprio id, para que o item correto seja atualizado;}  pedido[itens_attributes][][quantidade]’ }  Junto do ID vem o atributo (ou os atributos) que você deseja alterar;}  Veja que entre o [itens_attributes] e [id] existe um “[]”, esse par de colchetes serve pra definir que você está alterando um array de itens; 10
  11. 11. Formato do formulário que está sendoenviado para o controller}  "pedido"=> }  {"itens_attributes"=>[ }  {"id"=>"1","quantidade"=>"5"}, }  {"id"=>"2","quantidade"=>"4"}, }  {"id"=>"3","quantidade"=>"8”} }  ]} 11
  12. 12. Adicionando uma nova rota}  map.resources :itens, :collection => { :atualizar_carrinho => :post }}  Ações do tipo “collection” são definidas quando você vai chamar um método do controller que não afeta um recurso em específico, a URL gerada seria “/itens/ atualizar_carrinho”;}  A outra opção seria usar ações do tipo “member”, que afetam recursos específicos, a URL gerada seria “/itens/ nome_da_acao/1” 12
  13. 13. Implementando o controllerdef atualizar_carrinho pedido_atual.update_attributes( params[:pedido] ) respond_to do |format| format.html do flash[:success] = Carrinho de compras atualizado comsucesso redirect_to itens_path end endend 13
  14. 14. Removendo itens que tenham a quantidademenor do que 1}  O ActiveRecord define vários hooks (“ganchos”) onde você pode executar código durante o ciclo de vida de um objeto: }  before_validation }  before_validation_on_create }  validate_on_create }  after_validation }  after_validation_on_create }  before_save }  before_create }  after_create }  after_save 14
  15. 15. Ganchos do ActiveRecord}  Esses ganchos podem ser utilizados para executar código nas suas classes, como fazer cache de valores, preencher os objetos com dados padrão;}  Você pode definir vários métodos para um mesmo gancho, todos eles são executados na sequência em que foram definidos;}  Quando um método retorna “false”, ele pára a execução de todos os ganchos que vem após ele; 15
  16. 16. Implementando um ganchoclass Pedido < ActiveRecord::Base has_many :itens, :dependent => :destroy accepts_nested_attributes_for :itens after_save :remover_itens_zerados # resto do código protected def remover_itens_zerados zerados = self.itens.find_all { |item| item.quantidade.to_i < 1 } self.itens.delete( *zerados ) endend 16
  17. 17. self.itens.delete( *args ) – métodosencontrados em associações}  itens.delete – remove objetos da associação (apagando ele do banco se o :dependent for :destroy ou :delete_all)}  itens(true) – atualiza a coleção pra os valores mais atuais no banco}  itens.item_ids – traz os ids dos objetos associados}  itens.find – faz uma consulta no banco apenas nos objetos que fazem parte da associação}  Outros métodos em -> http://api.rubyonrails.org/classes/ActiveRecord/Associations/ ClassMethods.html#method-i-has_many 17
  18. 18. Montando a administração do site}  Vive em um caminho/namespace separado do site principal (como em “/admin”);}  Normalmente precisa de um controle de acesso mais complexo, liberando apenas para usuários que sejam administradores;}  Também precisa de um layout específico pra ela, em vez de usar o layout comum do site; 18
  19. 19. Criando o controller base da administraçàoclass Admin::BaseController < ApplicationController layout administracaoend 19
  20. 20. Pastas}  O arquivo do controller deve ser base_controller.rb e deve ser criado dentro da pasta “app/controllers/admin”;}  Quando um controller tem um namespace ( Admin::BaseController ), a pasta onde ele fica deve representar o mesmo caminho do namespace dele;}  O nome final do arquivo é o nome do controller SEM o namespace; 20
  21. 21. Criando o controller base da administração}  No controller fazemos a uma chamada ao método “layout” e passamos como parâmetro a string “administracao”;}  Isso define que o controller Admin::BaseController não vai mais utilizar o layout “application.html.erb” mas sim o “administracao.html.erb”;}  Cada controller pode definir o seu próprio layout base com a chamada do método “layout”; 21
  22. 22. Configurando as rotas com namespacenamespace :admin do resources :produtosend 22
  23. 23. rake routes | grep admin}  admin_produtos GET /admin/produtos}  POST /admin/produtos}  new_admin_produto GET /admin/produtos/new}  edit_admin_produto GET /admin/produtos/:id/edit}  admin_produto GET admin/produtos/:id}  PUT /admin/produtos/:id}  DELETE /admin/produtos/:id 23
  24. 24. Instalando a gem de paginação}  Instalando a gem }  gem install will_paginate}  Configurando ela no environment.rb }  config.gem “will_paginate” 24
  25. 25. Adicionando métodos de paginação emApplicationControllerclass ApplicationController < ActionController::Base #outros métodos protected def load_page @page = params[:page] || 1 @per_page = params[:per_page] || 10 end def paginate( scope, options = {} ) load_page scope.paginate( :page => @page, :per_page => @per_page ) endend 25
  26. 26. Métodos básicos - admin/produtos_controller.rbclass Admin::ProdutosController < Admin::BaseController before_filter :load_produto, :only => [ :new, :edit, :create, :update, :destroy ] #mais código aqui protected def load_produto @produto = params[:id].blank? ? Produto.new : Produto.find( params[:id] ) end def ir_para_listagem( mensagem ) respond_to do |format| format.html do flash[:success] = mensagem redirect_to admin_produtos_path end end endend 26
  27. 27. before_filter}  Define métodos a serem executados antes da ação do controller ser executada;}  Normalmente são utilizados para transformar dados da sessão em variáveis para o controller ou validar se a requisição é válida ou não;}  Podem ser aplicados a todos os métodos de um controller ou apenas a alguns com :only e :except; 27
  28. 28. Criando e editando produtos – admin/produtos_controller.rbdef new respond_to do |format| format.html do render :new end endendalias :edit :newdef create if @produto.update_attributes( params[:produto] ) ir_para_listagem( Produto criado/atualizado com sucesso ) else new endendalias :update :create 28
  29. 29. alias}  alias :edit :new }  Crie um método “edit” que aponte para o método “new”}  Simplifica a definição de controllers, já que os métodos “new” e “edit” fazem a mesma coisa;}  O funcionamento é o mesmo para “create” e “update”, os métodos fazem a mesma coisa, então definir um alias é mais prático; 29
  30. 30. Listando e removendo produtos – admin/produtos_controller.rbdef index @produtos = paginate( Produto ) respond_to do |format| format.html endenddef destroy @produto.destroy ir_para_listagem( Produto removido com sucesso )end 30
  31. 31. Preparando a listagem de produtos daadministração – admin/produtos/index<% unless @produtos.blank? %> <%= will_paginate @produtos %> <table> <%= cabecalho_de_tabela Nome, Preço, Ações %> <tbody> <%= render @produtos %> </tbody> </table> <%= will_paginate @produtos %><% else %> <p> Não há produtos cadastrados no sistema. </p><% end %> 31
  32. 32. Definindo um método emapplication_helper.rbmodule ApplicationHelper def cabecalho_de_tabela( *nomes ) colunas = nomes.map { |nome| "<th>#{nome}</th>" } linha = content_tag( :tr, colunas.join("n").html_safe ) content_tag( :thead, linha ).html_safe endend 32
  33. 33. Definindo um método emapplication_helper.rb}  Métodos definidos em quaisquer arquivos dentro da pasta helper estão disponíveis por padrão em todas as views da sua aplicação;}  Você deve agrupar os métodos em helpers dependendo da funcionalidade que implementam ou modelo sobre o qual interagem;}  Não defina todos os seus métodos em application_helper.rb, crie outros arquivos de helper para organizar o seu código J 33
  34. 34. <%= will_paginate @produtos %>}  O método de views will_paginate vai gerar na sua view um controle de paginação com os números de páginas e os botões anterior e próximo;}  O parâmetro que ele recebe é uma coleção que tenha sido retornada através de um método paginate em um dos seus models, uma coleção normal não vai ser aceita;}  Você pode personalizar as mensagens ou o HTML gerado através de opções passadas para esse método; 34
  35. 35. <%= render @produtos %>}  Atalho para gerar uma lista de objetos que compartilham o mesmo partial; No caso do exemplo, é equivalente a fazer:}  <% @produtos.each do |produto| %> <%= render “admin/produtos/produto”, :produto =>produto %> <% end %>}  O caminho do partial a ser buscado vai ser sempre “caminho_atual/nome_da_classe_no_singular” 35
  36. 36. Linha de produto – admin/produtos/_produto.html.erb<tr> <td> <%= produto.nome %> </td> <td> <%= number_to_currency produto.preco %> </td> <td> <%= link_to Editar, edit_admin_produto_path(produto) %> | <%= link_to Remover’, admin_produto_path(produto), :method => :delete, :confirm => Tem certeza de que deseja remover esteproduto? %> </td></tr> 36
  37. 37. link_to - :method => :delete}  Links em HTML geram, por padrão, uma requisição do tipo GET, mas no nosso caso precisamos que um link gere uma requisição do tipo :delete;}  O Rails oferece uma opção chamada :method para links para que eles possam executar chamadas a outros métodos HTTP;}  Além disso também é possível usar a opção :confirm para validar se o usuário quer realmente efetuar aquela ação; 37
  38. 38. Criando um helper para simplificar oformulário de produtosmodule Admin::ProdutosHelper def admin_form_for_produto( &block ) opcoes = if @produto.new_record? [admin_produtos_path, :post] else [admin_produto_path( @produto ), :put] end form_for( @produto, :url => opcoes.first, :html => { :method => opcoes.last }, &block ) endend 38
  39. 39. RESTful forms}  Formulários em Rails seguem a padronização RESTful que as rotas para os métodos definem;}  Para criar um novo produto, é necessário um POST em “/ admin/produtos”, para editar um produto é necessário um PUT em “/admin/produtos/ID”;}  O método admin_form_for_produto usa o método new_record? de Produto para saber se ele está criando um novo ou editando um produto existente; 39
  40. 40. Formulário de criação/edição de produtos<%= admin_form_for_produto do |f| %> <%= error_messages_for @produto %> <p> Nome: <br/> <%= f.text_field :nome %> </p> <p> Preço: <br/> <%= f.text_field :preco %> </p> <p> Descrição: <br/> <%= f.text_area :descricao %> </p> <p> <%= submit_tag Enviar %> </p><% end %> 40
  41. 41. Implementando o helper para mostrar oserrosmodule ApplicationHelper def error_messages_for( object, title = Foram encontradoserros nos seus dados ) if object render compartilhados/erros, :title => title, :errors => object.errors.full_messages end endend 41
  42. 42. E o HTML – app/views/compartilhados/_erros.html.erb<div class="alert-message block-message error"> <a class="close" href="#">&times;</a> <p><strong> <%= title %> </strong></p> <ul> <% errors.each do |error| %> <li><%= error %></li> <% end %> </ul></div> 42

×