SlideShare una empresa de Scribd logo
1 de 42
Descargar para leer sin conexión
Aprendendo Ruby on Rails - Aula 3


                     Maurício Linhares
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
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
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
<%= 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
Alterando vários itens ao mesmo tempo no
carrinho – 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
Na classe Pedido
class Pedido < ActiveRecord::Base

 has_many :itens

 accepts_nested_attributes_for :itens

 #resto dos métodos

end


 7
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
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
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
Formato do formulário que está sendo
enviado para o controller



}    "pedido"=>
      }    {"itens_attributes"=>[
            }    {"id"=>"1","quantidade"=>"5"},
            }    {"id"=>"2","quantidade"=>"4"},
            }    {"id"=>"3","quantidade"=>"8”}
      }    ]}




  11
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
Implementando o controller
def atualizar_carrinho
 pedido_atual.update_attributes( params[:pedido] )
 respond_to do |format|
   format.html do
     flash[:success] = 'Carrinho de compras atualizado com
sucesso'
     redirect_to itens_path
   end
 end
end

 13
Removendo itens que tenham a quantidade
menor 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
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
Implementando um gancho
class 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 )
 end

end

 16
self.itens.delete( *args ) – métodos
encontrados 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
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
Criando o controller base da administraçào



class Admin::BaseController < ApplicationController

 layout 'administracao'

end




 19
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
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
Configurando as rotas com namespace


namespace :admin do
  resources :produtos
end




 22
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
Instalando a gem de paginação


}      Instalando a gem
      }    gem install will_paginate
}    Configurando ela no environment.rb
      }    config.gem “will_paginate”




  24
Adicionando métodos de paginação em
ApplicationController
class 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 )
 end

end



 25
Métodos básicos - admin/
produtos_controller.rb
class 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
 end

end



  26
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
Criando e editando produtos – admin/
produtos_controller.rb
def new
 respond_to do |format|
  format.html do
    render :new
  end
 end
end

alias :edit :new

def create
 if @produto.update_attributes( params[:produto] )
   ir_para_listagem( 'Produto criado/atualizado com sucesso' )
 else
   new
 end
end

alias :update :create



  28
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
Listando e removendo produtos – admin/
produtos_controller.rb
def index
 @produtos = paginate( Produto )
 respond_to do |format|
  format.html
 end
end

def destroy
 @produto.destroy
 ir_para_listagem( 'Produto removido com sucesso' )
end

 30
Preparando a listagem de produtos da
administraçã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
Definindo um método em
application_helper.rb
module 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

 end

end

 32
Definindo um método em
application_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
<%= 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
<%= 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
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 este
produto?' %>
 </td>
</tr>

 36
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
Criando um helper para simplificar o
formulário de produtos
module 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 )
 end

end

 38
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
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
Implementando o helper para mostrar os
erros
module ApplicationHelper

 def error_messages_for( object, title = 'Foram encontrados
erros nos seus dados' )
   if object
     render 'compartilhados/erros',
          :title => title,
          :errors => object.errors.full_messages
   end
 end


end

 41
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

Más contenido relacionado

Similar a Curso de Ruby on Rails - Aula 03

Desenvolvimento de Apps e Games para Android - Parte 6
Desenvolvimento de Apps e Games para Android - Parte 6Desenvolvimento de Apps e Games para Android - Parte 6
Desenvolvimento de Apps e Games para Android - Parte 6
Erisvaldo Junior
 
Desenvolvimento de Apps e Games para Android - Parte 5
Desenvolvimento de Apps e Games para Android - Parte 5Desenvolvimento de Apps e Games para Android - Parte 5
Desenvolvimento de Apps e Games para Android - Parte 5
Erisvaldo Junior
 

Similar a Curso de Ruby on Rails - Aula 03 (20)

Curso de Ruby on Rails - Aula 01
Curso de Ruby on Rails - Aula 01Curso de Ruby on Rails - Aula 01
Curso de Ruby on Rails - Aula 01
 
Estrutura do Projeto
Estrutura do ProjetoEstrutura do Projeto
Estrutura do Projeto
 
Estrutura do Projeto
Estrutura do ProjetoEstrutura do Projeto
Estrutura do Projeto
 
Desenvolvimento de Apps e Games para Android - Parte 6
Desenvolvimento de Apps e Games para Android - Parte 6Desenvolvimento de Apps e Games para Android - Parte 6
Desenvolvimento de Apps e Games para Android - Parte 6
 
ZF Básico - 3. Quick Start
ZF Básico - 3. Quick StartZF Básico - 3. Quick Start
ZF Básico - 3. Quick Start
 
Desenvolvimento de Sistemas Web com PHP Frameworks - Aula 3 - 2019.1
Desenvolvimento de Sistemas Web com PHP Frameworks - Aula 3 - 2019.1Desenvolvimento de Sistemas Web com PHP Frameworks - Aula 3 - 2019.1
Desenvolvimento de Sistemas Web com PHP Frameworks - Aula 3 - 2019.1
 
ZF Básico - 5. Modelo
ZF Básico - 5. ModeloZF Básico - 5. Modelo
ZF Básico - 5. Modelo
 
Interfaces ricas com Rails e React.JS @ Rubyconf 2015
Interfaces ricas com Rails e React.JS @ Rubyconf 2015Interfaces ricas com Rails e React.JS @ Rubyconf 2015
Interfaces ricas com Rails e React.JS @ Rubyconf 2015
 
Play Framework - FLISOL
Play Framework - FLISOLPlay Framework - FLISOL
Play Framework - FLISOL
 
Zend Framework - PHPSP - 2009
Zend Framework - PHPSP - 2009Zend Framework - PHPSP - 2009
Zend Framework - PHPSP - 2009
 
Introdução ao Zend Framework 2
Introdução ao Zend Framework 2Introdução ao Zend Framework 2
Introdução ao Zend Framework 2
 
Desenvolvimento de Sistemas Web com PHP Frameworks - 2019.1 - Aula 1
Desenvolvimento de Sistemas Web com PHP Frameworks - 2019.1 - Aula 1Desenvolvimento de Sistemas Web com PHP Frameworks - 2019.1 - Aula 1
Desenvolvimento de Sistemas Web com PHP Frameworks - 2019.1 - Aula 1
 
Desenvolvimento de Apps e Games para Android - Parte 5
Desenvolvimento de Apps e Games para Android - Parte 5Desenvolvimento de Apps e Games para Android - Parte 5
Desenvolvimento de Apps e Games para Android - Parte 5
 
Model View Controller
Model View ControllerModel View Controller
Model View Controller
 
Modulos SNEP
Modulos SNEPModulos SNEP
Modulos SNEP
 
ZF Básico - 4. Controle e Visão
ZF Básico - 4. Controle e VisãoZF Básico - 4. Controle e Visão
ZF Básico - 4. Controle e Visão
 
ASP .NET 4.0 WebForms, Novas funcionalidades
ASP .NET 4.0 WebForms, Novas funcionalidadesASP .NET 4.0 WebForms, Novas funcionalidades
ASP .NET 4.0 WebForms, Novas funcionalidades
 
Introdução ao Symfony 2 - SfCon 2012
Introdução ao Symfony 2 - SfCon 2012Introdução ao Symfony 2 - SfCon 2012
Introdução ao Symfony 2 - SfCon 2012
 
Tutorial struts
Tutorial strutsTutorial struts
Tutorial struts
 
PHP FrameWARks - FISL
PHP FrameWARks - FISLPHP FrameWARks - FISL
PHP FrameWARks - FISL
 

Más de Maurício Linhares

Curso java 08 - mais sobre coleções
Curso java   08 - mais sobre coleçõesCurso java   08 - mais sobre coleções
Curso java 08 - mais sobre coleções
Maurício Linhares
 
Curso java 06 - mais construtores, interfaces e polimorfismo
Curso java   06 - mais construtores, interfaces e polimorfismoCurso java   06 - mais construtores, interfaces e polimorfismo
Curso java 06 - mais construtores, interfaces e polimorfismo
Maurício Linhares
 
Curso java 05 - herança, classes e métodos abstratos
Curso java   05 - herança, classes e métodos abstratosCurso java   05 - herança, classes e métodos abstratos
Curso java 05 - herança, classes e métodos abstratos
Maurício Linhares
 
Curso java 04 - ap is e bibliotecas
Curso java   04 - ap is e bibliotecasCurso java   04 - ap is e bibliotecas
Curso java 04 - ap is e bibliotecas
Maurício Linhares
 
Curso java 01 - molhando os pés com java
Curso java   01 - molhando os pés com javaCurso java   01 - molhando os pés com java
Curso java 01 - molhando os pés com java
Maurício Linhares
 
Curso java 03 - métodos e parâmetros
Curso java   03 - métodos e parâmetrosCurso java   03 - métodos e parâmetros
Curso java 03 - métodos e parâmetros
Maurício Linhares
 
Aulas de Java Avançado 2- Faculdade iDez 2010
Aulas de Java Avançado 2- Faculdade iDez 2010Aulas de Java Avançado 2- Faculdade iDez 2010
Aulas de Java Avançado 2- Faculdade iDez 2010
Maurício Linhares
 

Más de Maurício Linhares (20)

Mercado de TI
Mercado de TIMercado de TI
Mercado de TI
 
Unindo Ruby e Java através de uma arquitetura orientada a serviços na OfficeDrop
Unindo Ruby e Java através de uma arquitetura orientada a serviços na OfficeDropUnindo Ruby e Java através de uma arquitetura orientada a serviços na OfficeDrop
Unindo Ruby e Java através de uma arquitetura orientada a serviços na OfficeDrop
 
Mixing Ruby and Java in a Service Oriented Architecture at OfficeDrop
Mixing Ruby and Java in a Service Oriented Architecture at OfficeDropMixing Ruby and Java in a Service Oriented Architecture at OfficeDrop
Mixing Ruby and Java in a Service Oriented Architecture at OfficeDrop
 
Aprendendo ruby
Aprendendo rubyAprendendo ruby
Aprendendo ruby
 
Curso java 07 - exceções
Curso java   07 - exceçõesCurso java   07 - exceções
Curso java 07 - exceções
 
Curso java 08 - mais sobre coleções
Curso java   08 - mais sobre coleçõesCurso java   08 - mais sobre coleções
Curso java 08 - mais sobre coleções
 
Curso java 06 - mais construtores, interfaces e polimorfismo
Curso java   06 - mais construtores, interfaces e polimorfismoCurso java   06 - mais construtores, interfaces e polimorfismo
Curso java 06 - mais construtores, interfaces e polimorfismo
 
Curso java 05 - herança, classes e métodos abstratos
Curso java   05 - herança, classes e métodos abstratosCurso java   05 - herança, classes e métodos abstratos
Curso java 05 - herança, classes e métodos abstratos
 
Curso java 04 - ap is e bibliotecas
Curso java   04 - ap is e bibliotecasCurso java   04 - ap is e bibliotecas
Curso java 04 - ap is e bibliotecas
 
Curso java 01 - molhando os pés com java
Curso java   01 - molhando os pés com javaCurso java   01 - molhando os pés com java
Curso java 01 - molhando os pés com java
 
Curso java 02 - variáveis
Curso java   02 - variáveisCurso java   02 - variáveis
Curso java 02 - variáveis
 
Curso java 03 - métodos e parâmetros
Curso java   03 - métodos e parâmetrosCurso java   03 - métodos e parâmetros
Curso java 03 - métodos e parâmetros
 
Extreme programming
Extreme programmingExtreme programming
Extreme programming
 
Feature Driven Development
Feature Driven DevelopmentFeature Driven Development
Feature Driven Development
 
Migrando pra Scala
Migrando pra ScalaMigrando pra Scala
Migrando pra Scala
 
Outsourcing e trabalho remoto para a nuvem
Outsourcing e trabalho remoto para a nuvemOutsourcing e trabalho remoto para a nuvem
Outsourcing e trabalho remoto para a nuvem
 
Mercado hoje
Mercado hojeMercado hoje
Mercado hoje
 
Análise de sistemas oo 1
Análise de sistemas oo   1Análise de sistemas oo   1
Análise de sistemas oo 1
 
Revisão html e java script
Revisão html e java scriptRevisão html e java script
Revisão html e java script
 
Aulas de Java Avançado 2- Faculdade iDez 2010
Aulas de Java Avançado 2- Faculdade iDez 2010Aulas de Java Avançado 2- Faculdade iDez 2010
Aulas de Java Avançado 2- Faculdade iDez 2010
 

Curso de Ruby on Rails - Aula 03

  • 1. Aprendendo Ruby on Rails - Aula 3 Maurício Linhares
  • 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. 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. 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. <%= 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. Alterando vários itens ao mesmo tempo no carrinho – 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. Na classe Pedido class Pedido < ActiveRecord::Base has_many :itens accepts_nested_attributes_for :itens #resto dos métodos end 7
  • 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. 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. 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. Formato do formulário que está sendo enviado para o controller }  "pedido"=> }  {"itens_attributes"=>[ }  {"id"=>"1","quantidade"=>"5"}, }  {"id"=>"2","quantidade"=>"4"}, }  {"id"=>"3","quantidade"=>"8”} }  ]} 11
  • 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. Implementando o controller def atualizar_carrinho pedido_atual.update_attributes( params[:pedido] ) respond_to do |format| format.html do flash[:success] = 'Carrinho de compras atualizado com sucesso' redirect_to itens_path end end end 13
  • 14. Removendo itens que tenham a quantidade menor 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. 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. Implementando um gancho class 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 ) end end 16
  • 17. self.itens.delete( *args ) – métodos encontrados 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. 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. Criando o controller base da administraçào class Admin::BaseController < ApplicationController layout 'administracao' end 19
  • 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. 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. Configurando as rotas com namespace namespace :admin do resources :produtos end 22
  • 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. Instalando a gem de paginação }  Instalando a gem }  gem install will_paginate }  Configurando ela no environment.rb }  config.gem “will_paginate” 24
  • 25. Adicionando métodos de paginação em ApplicationController class 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 ) end end 25
  • 26. Métodos básicos - admin/ produtos_controller.rb class 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 end end 26
  • 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. Criando e editando produtos – admin/ produtos_controller.rb def new respond_to do |format| format.html do render :new end end end alias :edit :new def create if @produto.update_attributes( params[:produto] ) ir_para_listagem( 'Produto criado/atualizado com sucesso' ) else new end end alias :update :create 28
  • 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. Listando e removendo produtos – admin/ produtos_controller.rb def index @produtos = paginate( Produto ) respond_to do |format| format.html end end def destroy @produto.destroy ir_para_listagem( 'Produto removido com sucesso' ) end 30
  • 31. Preparando a listagem de produtos da administraçã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. Definindo um método em application_helper.rb module 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 end end 32
  • 33. Definindo um método em application_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. <%= 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. <%= 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. 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 este produto?' %> </td> </tr> 36
  • 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. Criando um helper para simplificar o formulário de produtos module 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 ) end end 38
  • 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. 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. Implementando o helper para mostrar os erros module ApplicationHelper def error_messages_for( object, title = 'Foram encontrados erros nos seus dados' ) if object render 'compartilhados/erros', :title => title, :errors => object.errors.full_messages end end end 41
  • 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