SlideShare uma empresa Scribd logo
1 de 50
Baixar para ler offline
Aprendendo Ruby on Rails – Aula 4


                     Maurício Linhares
Mas o design do meu formulário não
         está igual ao do Bootstrap!

                   Form Builders to the rescue!
Ao trabalhar com formulários em Rails, use
sempre form-builders
}    Forma padronizada de lidar com formulários no Rails;



}    Faz com que você organize o markup/html/css da sua
      aplicação de forma mais limpa;



}    Oficializa o reuso de formulários HTML por todo o site,
      além de garantir que os estilos são os mesmos em todos
      os lugares;
Como implementar um form-builder?
}    O que você quer fazer é implementar um Decorator que
      vai cobrir o form builder padrão do Rails;

}    Reuse as chamadas que já existem e adicione ou
      empacote o resultado do form builder padrão com os
      seus estilos personalizados;

}    O Bootstrap do twitter foi feito sob medida pra ser
      utilizado com form builders do Rails;
Iniciando a implementação – app/helpers/
bootstrap_form_builder.rb
class BootstrapFormBuilder < ActionView::Helpers::FormBuilder

 def get_error_text(field)
  self.object && self.object.errors[field].first
 end

 def content_tag(*args)
  @template.content_tag(*args).html_safe
 end

 def render_label(field, title)
  label(title.blank? ? self.object.class.human_attribute_name(field) : title)
 end

end
Começando a magia – define_method
class BootstrapFormBuilder < ActionView::Helpers::FormBuilder

basic_helpers = %w{text_field text_area select password_field file_field}

 basic_helpers.each do |name|

  define_method(name) do |field, *args|
   options = args.last.is_a?(Hash) ? args.last : {}

      label   = render_label(field, options[:label])
      error_text = get_error_text(field)

   wrap_field(label, super(field, *args), error_text)
  end

 end

end
Como assim define_method?
}    Define um método em tempo de execução dentro de um
      objeto (a técnica é comumente conhecida como
      metaprogramação);

}    No nosso caso, que é a implementação de um Decorator,
      é a solução ideal, pois provê uma forma genérica de
      adicionar a mesma funcionalidade aos vários métodos que
      precisam dela, sem repetição;
Implementando wrap_field
def wrap_field(label, content, error_text)

  wrapper_class = ['clearfix']
  unless error_text.blank?
   wrapper_class << 'error'
  end

  result = [content]

  unless error_text.blank?
   result << content_tag(:span, error_text, :class => 'help-inline')
  end

  result = result.join(' ').html_safe

  @template.content_tag(:div, label + content_tag(:div, result, :class => 'input'), :class =>
wrapper_class.join(' '))
 end
Implementando para campos que tem vários
itens de formulário
multipart_helpers = %w{date_select datetime_select}

multipart_helpers.each do |name|
 define_method(name) do |field, *args|
  options = args.last.is_a?(Hash) ? args.last : {}

   label = render_label(field, options[:label])

   error_text = get_error_text(object, field)

  wrap_multipart_field(label, super(field, *args), error_text)
 end
end
Empacotando campos com vários itens
def wrap_multipart_field(label, content, error_text)

  wrapper_class = ['clearfix']
  unless error_text.blank?
   wrapper_class << 'error'
  end

  result = [content]

  unless error_text.blank?
   result << content_tag(:span, error_text, :class => 'help-inline')
  end

  result = content_tag(:div, result.join(' ').html_safe, :class => 'inline-inputs')

  @template.content_tag(:div, label + content_tag(:div, result, :class => 'input'), :class =>
wrapper_class.join(' '))
 end
Detalhe especial
}    Ao usar human_attribute_name o seu objeto precisa ter a tradução
      dos atributos definida, como em:

“pt-BR”:!
  activerecord:!
    models:!
      produto:!
        one: Produto!
        other: Produtos!
    attributes:!
      produto:!
        preco: Preço!
        nome: Nome!
        descricao: Descrição!
Alterando o formulário de produtos pra usar
o novo Form Builder
<%= admin_form_for_produto do |f| %>
  <fieldset>
   <legend> Criar/Editar Produto </legend>
   <%= error_messages_for @produto %>
   <%= f.text_field :nome %>
   <%= f.text_field :preco %>
   <%= f.text_area :descricao %>
   <div class="actions">
     <%= submit_tag 'Enviar', :class => 'btn primary' %>
   </div>
  </fieldset>
<% end %>
Alterando o método que abre o formulário –
app/helpers/admin/produtos_helper.rb
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 },
    :builder => BootstrapFormBuilder, &block )
 end

end
Criando os usuários
}    Os usuários da aplicação englobam tanto as pessoas que
      vão vir fazer compras no site como também os
      administradores que vão alimentar a administração;

}    Os usuários serão cadastrados através de suas contas de
      email e serão marcados como usuários comuns ou
      administradores;
Migração da tabela de usuários -
CriarUsuarios
def self.up
  create_table :usuarios do |t|
    t.string :email, :null => false
    t.boolean :administrador, :default => false, :null => false
    t.string :nome, :null => false
    t.string :salt, :null => false
    t.string :senha_em_hash, :null => false
    t.datetime :ultimo_acesso_em
    t.timestamps
  end

  add_index :usuarios, :email, :unique => true
  add_index :usuarios, :ultimo_acesso_em

 add_column :pedidos, :usuario_id, :integer, :null => true
 add_index :pedidos, :usuario_id
end

def self.down
 drop_table :usuarios
 remove_column :pedidos, :usuario_id
end
Criando a classe Usuario – validações e
campos virtuais
class Usuario < ActiveRecord::Base

 attr_accessor :senha, :termos_e_condicoes

 validates_presence_of    :nome, :email

 validates_acceptance_of :termos_e_condicoes, :if => :new_record?

 validates_presence_of    :senha_em_hash, :if => :senha_necessaria?

 validates_confirmation_of :senha, :if => :senha_necessaria?

 validates_length_of     :senha, :within => 4..40, :if => :senha_necessaria?

end
Senhas e segurança
}    Por motivos de segurança, você nunca deve gravar uma
      senha de um dos seus usuários no banco de dados em um
      formato onde os dados possam ser reconstruídos;

}    Senhas devem sempre ser gravadas em na forma de
      hashes, onde não é possível obter a senha novamente,
      apenas através de força bruta;

}    Não criptografe senhas, não as guarde em formatos que
      possam ser descobertos;
Definindo o controle de senhas do usuário
class Usuario < ActiveRecord::Base

 before_validation :hashear_senha

 def senha_necessaria?
  self.senha_em_hash.blank? || !self.senha.blank?
 end

 def senha_correta?( _senha )
  self.senha_em_hash == Usuario.hashear( _senha, self.salt )
 end

 protected

 def hashear_senha
  return true if self.senha.blank?
  self.salt = Digest::SHA1.hexdigest("--#{Time.now.to_s(:db)}--#{self.email}--#{self.nome}") if self.new_record?
  self.senha_em_hash = Usuario.hashear(self.senha, self.salt)
 end

end
Métodos de classe complementares
class Usuario < ActiveRecord::Base

class << self

  def hashear( senha, salt )
   Digest::SHA1.hexdigest("--#{salt}--#{senha}--")
  end

  def autenticar( email, senha )
   usuario = Usuario.first( :conditions => { :email => email } )
   if usuario && usuario.senha_correta?( senha )
     usuario
   else
     nil
   end
  end

 end

end
Usuários e Senhas
}    Os campos senha e senha_confirmation são ambos
      campos virtuais, eles existem apenas para ajudar a
      geração do hash da senha;

}    A senha nunca é gravada em lugar nenhum como o
      usuário a digitou, ela será sempre gravada como hash;

}    Ao fazer o login do usuário, nós recebemos o email e a
      senha digitada, mas transformamos ela no hash para
      poder fazer a comparação no método “autenticar”;
Preparando o applicaction_controller.rb para
o controle de usuários
def usuario_atual
 if @usuario_atual != false
   @usuario_atual = login_pela_sessao
 end
 @usuario_atual
end

def usuario_atual=( usuario )
 @usuario_atual = usuario
 session[:usuario_id] = usuario.id
end

def login_pela_sessao
 resultado = !session[:usuario_id].blank? &&
 Usuario.find_by_id( session[:usuario_id] )
 resultado ? resultado : false
end
Definindo o controle geral
}    O usuário que está atualmente logado na aplicação está
      acessível pelo método “usuario_atual”;

}    O método avalia se há um usuário na sessão, na
      chave :usuario_id e se não houver ele retorna “false”, para
      que o código saiba que não há um usuário logado no
      momento;

}    Se a variável @usuario_atual já estiver definida como
      “false”, ele não repete o teste, pois sabe que não há
      usuário logado no momento;
Preparando o application_controller.rb para
o controle de acesso de usuários

 helper_method :pedido_atual, :usuario_atual, :logged_in?, :
 administrador?

 def logged_in?
  self.usuario_atual
 end

 def administrador?
  logged_in? && self.usuario_atual.administrador?
 end
Filtros para controle de acesso
def login_necessario
  unless self.logged_in?

   respond_to do |format|
    format.html do
      flash[:erro] = 'Você precisa estar logado para acessar esta página'
      redirect_to sessao_path
    end
   end

  else
   true
  end

end
Filtros para controle de acesso
def administrador_necessario

 unless self.administrador?

   respond_to do |format|
    format.html do
      flash[:erro] = 'Você precisa ser um administrador para visualizar esta página'
      redirect_to sessao_path
    end
   end

 else
  true
 end

end
Filtros para controle de acesso
}    Os métodos login_necessario e
      administrador_necessario devem ser utilizados como
      “before_filter” em ações que requerem que o usuário
      esteja logado ou que seja um administrador;

}    O primeiro caso do uso é para os controllers da
      administração do site, apenas administradores devem ter
      acesso aquelas páginas;

}    Como o código causa um redirect se o usuário não for o
      que se espera, a execução da requisição pára no filtro;
Bloqueio de acesso apenas para
administradores

class Admin::BaseController < ApplicationController

 layout 'administracao'

 before_filter :administrador_necessario

end
Criando as contas de usuários –
usuarios_controller.rb
class UsuariosController < ApplicationController

 before_filter :login_necessario, :only => [ :edit, :update ]
 before_filter :load_usuario

 def new
  respond_to do |format|
   format.html { render :new }
  end
 end

 alias :edit :new
 alias :show :new

 protected

 def load_usuario
  @usuario = logged_in? ? self.usuario_atual : Usuario.new
 end

end
Criando contas de usuários –
usuarios_controller.rb
class UsuariosController < ApplicationController

 def create
  @usuario.attributes = params[:usuario]

  if @usuario.save
    self.usuario_atual = @usuario unless logged_in?
    respond_to do |format|
     format.html do
       flash[:notice] = 'Dados recebidos com sucesso'
       redirect_to produtos_path
     end
    end
  else
    self.new
  end

 end

end
Criando contas de usuários
}    Apenas usuários que estejam logados podem chamar as
      ações edit, já que há um filtro que faz o bloqueio das
      chamadas;

}    Se o usuário estiver sendo criado neste momento, ele é
      automaticamente logado no sistema, através da chamada:
      }    self.usuario_atual = @usuario


}    Se os dados não forem válidos, ele é retornado para a
      página do formulário;
Formulário de criação/edição de usuários
<%= form_for @usuario, :url => usuario_path, :html => { :method => :post} do |f| %>

 <%= f.error_messages %>

 <p>    Nome:     <br/>      <%= f.text_field :nome %> </p>

 <p>    Email:   <br/>      <%= f.text_field :email %> </p>

 <p>    Senha:   <br/>      <%= f.password_field :senha %> </p>

 <p>    Confirme a senha:     <br/>    <%= f.password_field :senha_confirmation %> </p>

 <% if @usuario.new_record? %>
  <p>     <%= f.check_box :termos_e_condicoes %>          Eu li e aceito os termos e condições   </p>
 <% end %>

 <p> <%= submit_tag 'Enviar' %> </p>

<% end %>
Formulário de criação de usuários
}    O formulário não referencia os campos salt ou
      senha_em_hash, apenas os campos virtuais senha,
      senha_confirmation e termos_e_condicoes;

}    Não é necessário gravar no banco de dados se o usuário
      aceitou ou não os termos e condições, se ele criou a
      conta, isso quer dizer que ele aceitou o campo;

}    Se nós não estamos mais criando um novo usuário, não é
      necessário mostrar o campo :termos_e_condicoes;
Rotas do tipo resource
}    Quando uma rota é definida como “resource” (no
      singular), significa que o recurso que ela representa é
      único (ou único para a aplicação ou único para o usuário
      atual);

}    Exemplos disso são o usuário que está atualmente logado
      ou os dados da sua conta;

}    Quando você define uma rota como “resource :usuario”
      as chamadas vão ser no singular, mas o nome do
      controller deve ser no plural, como em
      “UsuariosController”;
Criando rotas para usuários e sessões
resource :sessao
resource :usuario
Fazendo o login de usuários já existentes –
sessoes_controller.rb
class SessoesController < ApplicationController


 def new
  respond_to do |format|
      format.html do
        render :new
      end
  end
 end


 alias :show :new


 #logoff
 def destroy
  reset_session
  respond_to do |format|
   format.html do
       flash[:aviso] = 'Você saiu da aplicação com sucesso'
       redirect_to sessao_path
      end
  end
 end


end
Fazendo o login de usuários já existentes
 def create
  @usuario = Usuario.autenticar( params[:email] , params[:senha])
  if @usuario
    self.usuario_atual = @usuario
    respond_to do |format|
     format.html do
       flash[:aviso] = "Seja bem vindo a nossa loja, #{self.usuario_atual.nome}"
       redirect_to produtos_path
     end
    end
  else
    respond_to do |format|
     format.html do
       flash.now[:erro] = 'Não foi encontrado um usuário com o email e a senha que você forneceu'
       new
     end
    end
  end
end
Formulário de login de usuários – sessoes/
new.html.erb
<%= form_tag sessao_path do %>

 <p>
  Email:
  <br/>
  <%= text_field_tag :email, params[:email] %>
 </p>

 <p>
  Senha:
  <br/>
  <%= password_field_tag :senha %>
 </p>

 <p>   <%= submit_tag 'Enviar' %> </p>

<% end %>
Apagando as senhas até mesmo dos logs da
aplicação

class ApplicationController < ActionController::Base

 #remover estes parâmetros dos logs
 filter_parameter_logging :senha, :senha_confirmation

end
Fazendo a união do carrinho de compras do
usuário não logado com o usuário logado
def usuario_atual=( usuario )

  @usuario_atual = usuario
  session[:usuario_id] = usuario.id
  usuario.create_pedido_atual unless usuario.pedido_atual

  unless self.pedido_atual.blank?
   usuario.pedido_atual.unir( self.pedido_atual )
   self.pedido_atual.destroy
  end

  session[:pedido_id] = usuario.pedido_atual.id

end
Unindo carrinhos de compra
}    Se o usuário já estava adicionando itens ao carrinho antes
      de efetuar a compra, esses itens não podem ser perdidos;

}    Assim que o usuário é logado dentro do sistema, o seu
      pedido atual é unido com o pedido atual do usuário, de
      forma que nenhum dos itens é perdido;
Template para criar conta ou login –
compartilhados/_login_logout.html.erb
<% if logged_in? %>
 <p>
  Olá <%= usuario_atual.nome %>, seja bem vindo!
  <br/>
  <%= link_to 'Clique aqui para atualizar os seus dados de usuário', usuario_path %>
 </p>

 <p>
  <%= link_to 'Logoff', sessao_path, :method => :delete, :confirm => 'Tem certeza de que deseja sair da
   aplicação?' %>
 </p>

<% else %>
 <p>
  <%= link_to 'Já é usuário? Clique aqui para fazer login', sessao_path %>
  |
  <%= link_to 'Ainda não é usuário? Clique aqui para se cadastrar', usuario_path %>
 </p>
<% end %>
Enviando emails com Rails
}    O Rails vem com um componente padrão para o envio de
      emails, o ActionMailer;

}    Com ele, para enviar um email, você só precisa criar um
      objeto que herde de ActionMailer::Base e criar o
      template do texto do email a ser enviado;

}    Os emails podem conter texto em quaisquer formato,
      assim como anexos;
Configurando o SMTP – config/initializers/
email_configuration.rb
ActionMailer::Base.smtp_settings = {
  :enable_starttls_auto => true,
  :address => "smtp.gmail.com",
  :port => 587,
  :domain => "gmail.com",
  :authentication => :plain,
  :user_name => "linuxfi.ror.julho.2010@gmail.com",
  :password => "rubyonrails"
}
Criando um diretório para guardar os
mailers
}    Crie uma pasta chamada mailers em “app”

}    No seu environment.rb
      }    config.load_paths += [ "#{RAILS_ROOT}/app/mailers" ]
Criando uma classe base para os mailers –
app/mailers/base_mailer.rb

class BaseMailer < ActionMailer::Base

default_url_options[:host] = Rails.env.production? ?
 ’loja.com.br' : 'localhost:3000'
 default :from => 'contato@loja.com.br'

end
Por que uma classe base?
}    Adicionar métodos padrão para todos os mailers;

}    Adicionar configurações padrão que vão valer para todos
      os mailers da aplicação;

}    Facilitar a migração futura para uma fila de emails, como
      ar_mailer;
Implementação do mailer de usuarios –
app/mailers/usuarios_mailer.rb
class UsuariosMailer < BaseMailer

 def registro( usuario )
  @usuario = usuario
  mail(
   :to => usuario.email,
   :subject => ‘Seja bem vindo a loja virtual em Rails ‘)
 end

end
Email de registro de usuários – app/views/
usuarios_mailer/registro.text.erb

Olá <%= @usuario.nome %> ( <%= @usuario.email %> ),

Seja vem vindo a loja de exemplo do curso de Rails da
  LinuxFi.
Adicionando o código de envio de email na
hora que o usuário for criado
class Usuario < ActiveRecord::Base

 after_create     :enviar_email

 def enviar_email
  UsuariosMailer.registro( self ).deliver
 end

end
Enviando emails
}    Quando você define um método para envio de emails no
      seu mailer, a forma de chamar ele é:
      }    NomeDaClasse. nome_do_metodo( parametros ).deliver


}    Como em:
      }    UsuariosMailer. registro( usuario ).deliver


}    Isso vai fazer com que o ActionMailer gere o texto do
      email e o envie para o destinatário definido;

Mais conteúdo relacionado

Mais procurados

Javascript - Biblioteca Jquery
Javascript - Biblioteca JqueryJavascript - Biblioteca Jquery
Javascript - Biblioteca JqueryMultside Digital
 
PHP robusto com Zend Framework
PHP robusto com Zend FrameworkPHP robusto com Zend Framework
PHP robusto com Zend FrameworkJaime Neto
 
Play Framework - FLISOL
Play Framework - FLISOLPlay Framework - FLISOL
Play Framework - FLISOLgrupoweblovers
 
Rafael Garcia - Yii Framework, principais características e em ação
Rafael Garcia - Yii Framework, principais características e em açãoRafael Garcia - Yii Framework, principais características e em ação
Rafael Garcia - Yii Framework, principais características e em açãoRafael Garcia
 
Aplicações rápidas para a Web com Django
Aplicações rápidas para a Web com DjangoAplicações rápidas para a Web com Django
Aplicações rápidas para a Web com DjangoFreedom DayMS
 
Javascript truquesmagicos
Javascript truquesmagicosJavascript truquesmagicos
Javascript truquesmagicosponto hacker
 
Angular JS, você precisa conhecer
Angular JS, você precisa conhecerAngular JS, você precisa conhecer
Angular JS, você precisa conhecermeet2Brains
 
Formulários Web em PHP com plug-ins avançados e AJAX
Formulários Web em PHP com plug-ins avançados e AJAXFormulários Web em PHP com plug-ins avançados e AJAX
Formulários Web em PHP com plug-ins avançados e AJAXManuel Lemos
 
Evento Front End SP - Arquitetura de Front
Evento Front End SP - Arquitetura de FrontEvento Front End SP - Arquitetura de Front
Evento Front End SP - Arquitetura de FrontMichel Ribeiro
 
Slide 04 adicionando usuários e conhecendo o auto load
Slide 04   adicionando usuários e conhecendo o auto loadSlide 04   adicionando usuários e conhecendo o auto load
Slide 04 adicionando usuários e conhecendo o auto loadRaniere de Lima
 
Cuso Ruby - Aula 05 - Testes com RSpec
Cuso Ruby - Aula 05 - Testes com RSpecCuso Ruby - Aula 05 - Testes com RSpec
Cuso Ruby - Aula 05 - Testes com RSpecMaurício Linhares
 
Slide 01 introdução ao php e ao code igniter
Slide 01   introdução ao php e ao code igniterSlide 01   introdução ao php e ao code igniter
Slide 01 introdução ao php e ao code igniterRaniere de Lima
 

Mais procurados (18)

Java script aula 05 - funções
Java script   aula 05 - funçõesJava script   aula 05 - funções
Java script aula 05 - funções
 
Rich faces
Rich facesRich faces
Rich faces
 
Php 08 Oo
Php 08 OoPhp 08 Oo
Php 08 Oo
 
Slides
SlidesSlides
Slides
 
Javascript - Biblioteca Jquery
Javascript - Biblioteca JqueryJavascript - Biblioteca Jquery
Javascript - Biblioteca Jquery
 
Php 05 Mvc
Php 05 MvcPhp 05 Mvc
Php 05 Mvc
 
PHP robusto com Zend Framework
PHP robusto com Zend FrameworkPHP robusto com Zend Framework
PHP robusto com Zend Framework
 
Ns tutorial so
Ns tutorial soNs tutorial so
Ns tutorial so
 
Play Framework - FLISOL
Play Framework - FLISOLPlay Framework - FLISOL
Play Framework - FLISOL
 
Rafael Garcia - Yii Framework, principais características e em ação
Rafael Garcia - Yii Framework, principais características e em açãoRafael Garcia - Yii Framework, principais características e em ação
Rafael Garcia - Yii Framework, principais características e em ação
 
Aplicações rápidas para a Web com Django
Aplicações rápidas para a Web com DjangoAplicações rápidas para a Web com Django
Aplicações rápidas para a Web com Django
 
Javascript truquesmagicos
Javascript truquesmagicosJavascript truquesmagicos
Javascript truquesmagicos
 
Angular JS, você precisa conhecer
Angular JS, você precisa conhecerAngular JS, você precisa conhecer
Angular JS, você precisa conhecer
 
Formulários Web em PHP com plug-ins avançados e AJAX
Formulários Web em PHP com plug-ins avançados e AJAXFormulários Web em PHP com plug-ins avançados e AJAX
Formulários Web em PHP com plug-ins avançados e AJAX
 
Evento Front End SP - Arquitetura de Front
Evento Front End SP - Arquitetura de FrontEvento Front End SP - Arquitetura de Front
Evento Front End SP - Arquitetura de Front
 
Slide 04 adicionando usuários e conhecendo o auto load
Slide 04   adicionando usuários e conhecendo o auto loadSlide 04   adicionando usuários e conhecendo o auto load
Slide 04 adicionando usuários e conhecendo o auto load
 
Cuso Ruby - Aula 05 - Testes com RSpec
Cuso Ruby - Aula 05 - Testes com RSpecCuso Ruby - Aula 05 - Testes com RSpec
Cuso Ruby - Aula 05 - Testes com RSpec
 
Slide 01 introdução ao php e ao code igniter
Slide 01   introdução ao php e ao code igniterSlide 01   introdução ao php e ao code igniter
Slide 01 introdução ao php e ao code igniter
 

Semelhante a Curso de Ruby on Rails - Aula 04

Como criar um plugin para WordPress
Como criar um plugin para WordPressComo criar um plugin para WordPress
Como criar um plugin para WordPressLeandrinho Vieira
 
Desenvolvendo aplicações web com o framework cakephp
Desenvolvendo aplicações web com o framework cakephpDesenvolvendo aplicações web com o framework cakephp
Desenvolvendo aplicações web com o framework cakephpRodrigo Aramburu
 
Curso de Ruby on Rails - Aula 02
Curso de Ruby on Rails - Aula 02Curso de Ruby on Rails - Aula 02
Curso de Ruby on Rails - Aula 02Maurício Linhares
 
Django: Desenvolvendo uma aplicação web em minutos
Django: Desenvolvendo uma aplicação web em minutosDjango: Desenvolvendo uma aplicação web em minutos
Django: Desenvolvendo uma aplicação web em minutosRodrigo Nossal
 
Apresentação formação web - up marketing digital - módulo ii - 2º fds
Apresentação   formação web - up marketing digital - módulo ii - 2º fdsApresentação   formação web - up marketing digital - módulo ii - 2º fds
Apresentação formação web - up marketing digital - módulo ii - 2º fdsRangel Javier
 
Iniciando com Yii Framework - Volmar Machado da Silva Neto (Rede Pampa de Com...
Iniciando com Yii Framework - Volmar Machado da Silva Neto (Rede Pampa de Com...Iniciando com Yii Framework - Volmar Machado da Silva Neto (Rede Pampa de Com...
Iniciando com Yii Framework - Volmar Machado da Silva Neto (Rede Pampa de Com...Tchelinux
 
Mini Curso PHP Twig - PHP Conference 2017
Mini Curso PHP Twig - PHP Conference 2017 Mini Curso PHP Twig - PHP Conference 2017
Mini Curso PHP Twig - PHP Conference 2017 Luis Gustavo Almeida
 
Programação Web com Zend Framework e Ajax com Dojo
Programação Web com Zend Framework e Ajax com DojoProgramação Web com Zend Framework e Ajax com Dojo
Programação Web com Zend Framework e Ajax com Dojofabioginzel
 
Produtividade com JavaServer Faces
Produtividade com JavaServer FacesProdutividade com JavaServer Faces
Produtividade com JavaServer FacesEduardo Bregaida
 
Progweb Aula8
Progweb Aula8Progweb Aula8
Progweb Aula8softeam
 
Zend Framework - PHPSP - 2009
Zend Framework - PHPSP - 2009Zend Framework - PHPSP - 2009
Zend Framework - PHPSP - 2009silva.edgar
 
GURU SP - Design de aplicações orientadas a objeto
GURU SP - Design de aplicações orientadas a objetoGURU SP - Design de aplicações orientadas a objeto
GURU SP - Design de aplicações orientadas a objetoElaine Naomi
 
Introdução à análise orientada a objetos parte 1
Introdução à análise orientada a objetos parte 1Introdução à análise orientada a objetos parte 1
Introdução à análise orientada a objetos parte 1ariovaldodias
 

Semelhante a Curso de Ruby on Rails - Aula 04 (20)

Como criar um plugin para WordPress
Como criar um plugin para WordPressComo criar um plugin para WordPress
Como criar um plugin para WordPress
 
Desenvolvendo aplicações web com o framework cakephp
Desenvolvendo aplicações web com o framework cakephpDesenvolvendo aplicações web com o framework cakephp
Desenvolvendo aplicações web com o framework cakephp
 
Curso de Ruby on Rails - Aula 02
Curso de Ruby on Rails - Aula 02Curso de Ruby on Rails - Aula 02
Curso de Ruby on Rails - Aula 02
 
Django: Desenvolvendo uma aplicação web em minutos
Django: Desenvolvendo uma aplicação web em minutosDjango: Desenvolvendo uma aplicação web em minutos
Django: Desenvolvendo uma aplicação web em minutos
 
Apresentação formação web - up marketing digital - módulo ii - 2º fds
Apresentação   formação web - up marketing digital - módulo ii - 2º fdsApresentação   formação web - up marketing digital - módulo ii - 2º fds
Apresentação formação web - up marketing digital - módulo ii - 2º fds
 
Estrutura do Projeto
Estrutura do ProjetoEstrutura do Projeto
Estrutura do Projeto
 
Estrutura do Projeto
Estrutura do ProjetoEstrutura do Projeto
Estrutura do Projeto
 
Sistema php
Sistema phpSistema php
Sistema php
 
PHP FrameWARks - FISL
PHP FrameWARks - FISLPHP FrameWARks - FISL
PHP FrameWARks - FISL
 
Iniciando com Yii Framework - Volmar Machado da Silva Neto (Rede Pampa de Com...
Iniciando com Yii Framework - Volmar Machado da Silva Neto (Rede Pampa de Com...Iniciando com Yii Framework - Volmar Machado da Silva Neto (Rede Pampa de Com...
Iniciando com Yii Framework - Volmar Machado da Silva Neto (Rede Pampa de Com...
 
Workshop Django
Workshop DjangoWorkshop Django
Workshop Django
 
Mini Curso PHP Twig - PHP Conference 2017
Mini Curso PHP Twig - PHP Conference 2017 Mini Curso PHP Twig - PHP Conference 2017
Mini Curso PHP Twig - PHP Conference 2017
 
Programação Web com Zend Framework e Ajax com Dojo
Programação Web com Zend Framework e Ajax com DojoProgramação Web com Zend Framework e Ajax com Dojo
Programação Web com Zend Framework e Ajax com Dojo
 
Moodle api tutorial
Moodle api   tutorialMoodle api   tutorial
Moodle api tutorial
 
Produtividade com JavaServer Faces
Produtividade com JavaServer FacesProdutividade com JavaServer Faces
Produtividade com JavaServer Faces
 
Progweb Aula8
Progweb Aula8Progweb Aula8
Progweb Aula8
 
Zend Framework - PHPSP - 2009
Zend Framework - PHPSP - 2009Zend Framework - PHPSP - 2009
Zend Framework - PHPSP - 2009
 
Crud
CrudCrud
Crud
 
GURU SP - Design de aplicações orientadas a objeto
GURU SP - Design de aplicações orientadas a objetoGURU SP - Design de aplicações orientadas a objeto
GURU SP - Design de aplicações orientadas a objeto
 
Introdução à análise orientada a objetos parte 1
Introdução à análise orientada a objetos parte 1Introdução à análise orientada a objetos parte 1
Introdução à análise orientada a objetos parte 1
 

Mais de Maurício Linhares

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 OfficeDropMaurício Linhares
 
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 OfficeDropMaurí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çõesMaurí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 polimorfismoMaurí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 abstratosMaurí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 bibliotecasMaurí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 javaMaurí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âmetrosMaurício Linhares
 
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 nuvemMaurí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 2010Maurício Linhares
 

Mais 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 04

  • 1. Aprendendo Ruby on Rails – Aula 4 Maurício Linhares
  • 2. Mas o design do meu formulário não está igual ao do Bootstrap! Form Builders to the rescue!
  • 3. Ao trabalhar com formulários em Rails, use sempre form-builders }  Forma padronizada de lidar com formulários no Rails; }  Faz com que você organize o markup/html/css da sua aplicação de forma mais limpa; }  Oficializa o reuso de formulários HTML por todo o site, além de garantir que os estilos são os mesmos em todos os lugares;
  • 4. Como implementar um form-builder? }  O que você quer fazer é implementar um Decorator que vai cobrir o form builder padrão do Rails; }  Reuse as chamadas que já existem e adicione ou empacote o resultado do form builder padrão com os seus estilos personalizados; }  O Bootstrap do twitter foi feito sob medida pra ser utilizado com form builders do Rails;
  • 5. Iniciando a implementação – app/helpers/ bootstrap_form_builder.rb class BootstrapFormBuilder < ActionView::Helpers::FormBuilder def get_error_text(field) self.object && self.object.errors[field].first end def content_tag(*args) @template.content_tag(*args).html_safe end def render_label(field, title) label(title.blank? ? self.object.class.human_attribute_name(field) : title) end end
  • 6. Começando a magia – define_method class BootstrapFormBuilder < ActionView::Helpers::FormBuilder basic_helpers = %w{text_field text_area select password_field file_field} basic_helpers.each do |name| define_method(name) do |field, *args| options = args.last.is_a?(Hash) ? args.last : {} label = render_label(field, options[:label]) error_text = get_error_text(field) wrap_field(label, super(field, *args), error_text) end end end
  • 7. Como assim define_method? }  Define um método em tempo de execução dentro de um objeto (a técnica é comumente conhecida como metaprogramação); }  No nosso caso, que é a implementação de um Decorator, é a solução ideal, pois provê uma forma genérica de adicionar a mesma funcionalidade aos vários métodos que precisam dela, sem repetição;
  • 8. Implementando wrap_field def wrap_field(label, content, error_text) wrapper_class = ['clearfix'] unless error_text.blank? wrapper_class << 'error' end result = [content] unless error_text.blank? result << content_tag(:span, error_text, :class => 'help-inline') end result = result.join(' ').html_safe @template.content_tag(:div, label + content_tag(:div, result, :class => 'input'), :class => wrapper_class.join(' ')) end
  • 9. Implementando para campos que tem vários itens de formulário multipart_helpers = %w{date_select datetime_select} multipart_helpers.each do |name| define_method(name) do |field, *args| options = args.last.is_a?(Hash) ? args.last : {} label = render_label(field, options[:label]) error_text = get_error_text(object, field) wrap_multipart_field(label, super(field, *args), error_text) end end
  • 10. Empacotando campos com vários itens def wrap_multipart_field(label, content, error_text) wrapper_class = ['clearfix'] unless error_text.blank? wrapper_class << 'error' end result = [content] unless error_text.blank? result << content_tag(:span, error_text, :class => 'help-inline') end result = content_tag(:div, result.join(' ').html_safe, :class => 'inline-inputs') @template.content_tag(:div, label + content_tag(:div, result, :class => 'input'), :class => wrapper_class.join(' ')) end
  • 11. Detalhe especial }  Ao usar human_attribute_name o seu objeto precisa ter a tradução dos atributos definida, como em: “pt-BR”:! activerecord:! models:! produto:! one: Produto! other: Produtos! attributes:! produto:! preco: Preço! nome: Nome! descricao: Descrição!
  • 12. Alterando o formulário de produtos pra usar o novo Form Builder <%= admin_form_for_produto do |f| %> <fieldset> <legend> Criar/Editar Produto </legend> <%= error_messages_for @produto %> <%= f.text_field :nome %> <%= f.text_field :preco %> <%= f.text_area :descricao %> <div class="actions"> <%= submit_tag 'Enviar', :class => 'btn primary' %> </div> </fieldset> <% end %>
  • 13. Alterando o método que abre o formulário – app/helpers/admin/produtos_helper.rb 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 }, :builder => BootstrapFormBuilder, &block ) end end
  • 14. Criando os usuários }  Os usuários da aplicação englobam tanto as pessoas que vão vir fazer compras no site como também os administradores que vão alimentar a administração; }  Os usuários serão cadastrados através de suas contas de email e serão marcados como usuários comuns ou administradores;
  • 15. Migração da tabela de usuários - CriarUsuarios def self.up create_table :usuarios do |t| t.string :email, :null => false t.boolean :administrador, :default => false, :null => false t.string :nome, :null => false t.string :salt, :null => false t.string :senha_em_hash, :null => false t.datetime :ultimo_acesso_em t.timestamps end add_index :usuarios, :email, :unique => true add_index :usuarios, :ultimo_acesso_em add_column :pedidos, :usuario_id, :integer, :null => true add_index :pedidos, :usuario_id end def self.down drop_table :usuarios remove_column :pedidos, :usuario_id end
  • 16. Criando a classe Usuario – validações e campos virtuais class Usuario < ActiveRecord::Base attr_accessor :senha, :termos_e_condicoes validates_presence_of :nome, :email validates_acceptance_of :termos_e_condicoes, :if => :new_record? validates_presence_of :senha_em_hash, :if => :senha_necessaria? validates_confirmation_of :senha, :if => :senha_necessaria? validates_length_of :senha, :within => 4..40, :if => :senha_necessaria? end
  • 17. Senhas e segurança }  Por motivos de segurança, você nunca deve gravar uma senha de um dos seus usuários no banco de dados em um formato onde os dados possam ser reconstruídos; }  Senhas devem sempre ser gravadas em na forma de hashes, onde não é possível obter a senha novamente, apenas através de força bruta; }  Não criptografe senhas, não as guarde em formatos que possam ser descobertos;
  • 18. Definindo o controle de senhas do usuário class Usuario < ActiveRecord::Base before_validation :hashear_senha def senha_necessaria? self.senha_em_hash.blank? || !self.senha.blank? end def senha_correta?( _senha ) self.senha_em_hash == Usuario.hashear( _senha, self.salt ) end protected def hashear_senha return true if self.senha.blank? self.salt = Digest::SHA1.hexdigest("--#{Time.now.to_s(:db)}--#{self.email}--#{self.nome}") if self.new_record? self.senha_em_hash = Usuario.hashear(self.senha, self.salt) end end
  • 19. Métodos de classe complementares class Usuario < ActiveRecord::Base class << self def hashear( senha, salt ) Digest::SHA1.hexdigest("--#{salt}--#{senha}--") end def autenticar( email, senha ) usuario = Usuario.first( :conditions => { :email => email } ) if usuario && usuario.senha_correta?( senha ) usuario else nil end end end end
  • 20. Usuários e Senhas }  Os campos senha e senha_confirmation são ambos campos virtuais, eles existem apenas para ajudar a geração do hash da senha; }  A senha nunca é gravada em lugar nenhum como o usuário a digitou, ela será sempre gravada como hash; }  Ao fazer o login do usuário, nós recebemos o email e a senha digitada, mas transformamos ela no hash para poder fazer a comparação no método “autenticar”;
  • 21. Preparando o applicaction_controller.rb para o controle de usuários def usuario_atual if @usuario_atual != false @usuario_atual = login_pela_sessao end @usuario_atual end def usuario_atual=( usuario ) @usuario_atual = usuario session[:usuario_id] = usuario.id end def login_pela_sessao resultado = !session[:usuario_id].blank? && Usuario.find_by_id( session[:usuario_id] ) resultado ? resultado : false end
  • 22. Definindo o controle geral }  O usuário que está atualmente logado na aplicação está acessível pelo método “usuario_atual”; }  O método avalia se há um usuário na sessão, na chave :usuario_id e se não houver ele retorna “false”, para que o código saiba que não há um usuário logado no momento; }  Se a variável @usuario_atual já estiver definida como “false”, ele não repete o teste, pois sabe que não há usuário logado no momento;
  • 23. Preparando o application_controller.rb para o controle de acesso de usuários helper_method :pedido_atual, :usuario_atual, :logged_in?, : administrador? def logged_in? self.usuario_atual end def administrador? logged_in? && self.usuario_atual.administrador? end
  • 24. Filtros para controle de acesso def login_necessario unless self.logged_in? respond_to do |format| format.html do flash[:erro] = 'Você precisa estar logado para acessar esta página' redirect_to sessao_path end end else true end end
  • 25. Filtros para controle de acesso def administrador_necessario unless self.administrador? respond_to do |format| format.html do flash[:erro] = 'Você precisa ser um administrador para visualizar esta página' redirect_to sessao_path end end else true end end
  • 26. Filtros para controle de acesso }  Os métodos login_necessario e administrador_necessario devem ser utilizados como “before_filter” em ações que requerem que o usuário esteja logado ou que seja um administrador; }  O primeiro caso do uso é para os controllers da administração do site, apenas administradores devem ter acesso aquelas páginas; }  Como o código causa um redirect se o usuário não for o que se espera, a execução da requisição pára no filtro;
  • 27. Bloqueio de acesso apenas para administradores class Admin::BaseController < ApplicationController layout 'administracao' before_filter :administrador_necessario end
  • 28. Criando as contas de usuários – usuarios_controller.rb class UsuariosController < ApplicationController before_filter :login_necessario, :only => [ :edit, :update ] before_filter :load_usuario def new respond_to do |format| format.html { render :new } end end alias :edit :new alias :show :new protected def load_usuario @usuario = logged_in? ? self.usuario_atual : Usuario.new end end
  • 29. Criando contas de usuários – usuarios_controller.rb class UsuariosController < ApplicationController def create @usuario.attributes = params[:usuario] if @usuario.save self.usuario_atual = @usuario unless logged_in? respond_to do |format| format.html do flash[:notice] = 'Dados recebidos com sucesso' redirect_to produtos_path end end else self.new end end end
  • 30. Criando contas de usuários }  Apenas usuários que estejam logados podem chamar as ações edit, já que há um filtro que faz o bloqueio das chamadas; }  Se o usuário estiver sendo criado neste momento, ele é automaticamente logado no sistema, através da chamada: }  self.usuario_atual = @usuario }  Se os dados não forem válidos, ele é retornado para a página do formulário;
  • 31. Formulário de criação/edição de usuários <%= form_for @usuario, :url => usuario_path, :html => { :method => :post} do |f| %> <%= f.error_messages %> <p> Nome: <br/> <%= f.text_field :nome %> </p> <p> Email: <br/> <%= f.text_field :email %> </p> <p> Senha: <br/> <%= f.password_field :senha %> </p> <p> Confirme a senha: <br/> <%= f.password_field :senha_confirmation %> </p> <% if @usuario.new_record? %> <p> <%= f.check_box :termos_e_condicoes %> Eu li e aceito os termos e condições </p> <% end %> <p> <%= submit_tag 'Enviar' %> </p> <% end %>
  • 32. Formulário de criação de usuários }  O formulário não referencia os campos salt ou senha_em_hash, apenas os campos virtuais senha, senha_confirmation e termos_e_condicoes; }  Não é necessário gravar no banco de dados se o usuário aceitou ou não os termos e condições, se ele criou a conta, isso quer dizer que ele aceitou o campo; }  Se nós não estamos mais criando um novo usuário, não é necessário mostrar o campo :termos_e_condicoes;
  • 33. Rotas do tipo resource }  Quando uma rota é definida como “resource” (no singular), significa que o recurso que ela representa é único (ou único para a aplicação ou único para o usuário atual); }  Exemplos disso são o usuário que está atualmente logado ou os dados da sua conta; }  Quando você define uma rota como “resource :usuario” as chamadas vão ser no singular, mas o nome do controller deve ser no plural, como em “UsuariosController”;
  • 34. Criando rotas para usuários e sessões resource :sessao resource :usuario
  • 35. Fazendo o login de usuários já existentes – sessoes_controller.rb class SessoesController < ApplicationController def new respond_to do |format| format.html do render :new end end end alias :show :new #logoff def destroy reset_session respond_to do |format| format.html do flash[:aviso] = 'Você saiu da aplicação com sucesso' redirect_to sessao_path end end end end
  • 36. Fazendo o login de usuários já existentes def create @usuario = Usuario.autenticar( params[:email] , params[:senha]) if @usuario self.usuario_atual = @usuario respond_to do |format| format.html do flash[:aviso] = "Seja bem vindo a nossa loja, #{self.usuario_atual.nome}" redirect_to produtos_path end end else respond_to do |format| format.html do flash.now[:erro] = 'Não foi encontrado um usuário com o email e a senha que você forneceu' new end end end end
  • 37. Formulário de login de usuários – sessoes/ new.html.erb <%= form_tag sessao_path do %> <p> Email: <br/> <%= text_field_tag :email, params[:email] %> </p> <p> Senha: <br/> <%= password_field_tag :senha %> </p> <p> <%= submit_tag 'Enviar' %> </p> <% end %>
  • 38. Apagando as senhas até mesmo dos logs da aplicação class ApplicationController < ActionController::Base #remover estes parâmetros dos logs filter_parameter_logging :senha, :senha_confirmation end
  • 39. Fazendo a união do carrinho de compras do usuário não logado com o usuário logado def usuario_atual=( usuario ) @usuario_atual = usuario session[:usuario_id] = usuario.id usuario.create_pedido_atual unless usuario.pedido_atual unless self.pedido_atual.blank? usuario.pedido_atual.unir( self.pedido_atual ) self.pedido_atual.destroy end session[:pedido_id] = usuario.pedido_atual.id end
  • 40. Unindo carrinhos de compra }  Se o usuário já estava adicionando itens ao carrinho antes de efetuar a compra, esses itens não podem ser perdidos; }  Assim que o usuário é logado dentro do sistema, o seu pedido atual é unido com o pedido atual do usuário, de forma que nenhum dos itens é perdido;
  • 41. Template para criar conta ou login – compartilhados/_login_logout.html.erb <% if logged_in? %> <p> Olá <%= usuario_atual.nome %>, seja bem vindo! <br/> <%= link_to 'Clique aqui para atualizar os seus dados de usuário', usuario_path %> </p> <p> <%= link_to 'Logoff', sessao_path, :method => :delete, :confirm => 'Tem certeza de que deseja sair da aplicação?' %> </p> <% else %> <p> <%= link_to 'Já é usuário? Clique aqui para fazer login', sessao_path %> | <%= link_to 'Ainda não é usuário? Clique aqui para se cadastrar', usuario_path %> </p> <% end %>
  • 42. Enviando emails com Rails }  O Rails vem com um componente padrão para o envio de emails, o ActionMailer; }  Com ele, para enviar um email, você só precisa criar um objeto que herde de ActionMailer::Base e criar o template do texto do email a ser enviado; }  Os emails podem conter texto em quaisquer formato, assim como anexos;
  • 43. Configurando o SMTP – config/initializers/ email_configuration.rb ActionMailer::Base.smtp_settings = { :enable_starttls_auto => true, :address => "smtp.gmail.com", :port => 587, :domain => "gmail.com", :authentication => :plain, :user_name => "linuxfi.ror.julho.2010@gmail.com", :password => "rubyonrails" }
  • 44. Criando um diretório para guardar os mailers }  Crie uma pasta chamada mailers em “app” }  No seu environment.rb }  config.load_paths += [ "#{RAILS_ROOT}/app/mailers" ]
  • 45. Criando uma classe base para os mailers – app/mailers/base_mailer.rb class BaseMailer < ActionMailer::Base default_url_options[:host] = Rails.env.production? ? ’loja.com.br' : 'localhost:3000' default :from => 'contato@loja.com.br' end
  • 46. Por que uma classe base? }  Adicionar métodos padrão para todos os mailers; }  Adicionar configurações padrão que vão valer para todos os mailers da aplicação; }  Facilitar a migração futura para uma fila de emails, como ar_mailer;
  • 47. Implementação do mailer de usuarios – app/mailers/usuarios_mailer.rb class UsuariosMailer < BaseMailer def registro( usuario ) @usuario = usuario mail( :to => usuario.email, :subject => ‘Seja bem vindo a loja virtual em Rails ‘) end end
  • 48. Email de registro de usuários – app/views/ usuarios_mailer/registro.text.erb Olá <%= @usuario.nome %> ( <%= @usuario.email %> ), Seja vem vindo a loja de exemplo do curso de Rails da LinuxFi.
  • 49. Adicionando o código de envio de email na hora que o usuário for criado class Usuario < ActiveRecord::Base after_create :enviar_email def enviar_email UsuariosMailer.registro( self ).deliver end end
  • 50. Enviando emails }  Quando você define um método para envio de emails no seu mailer, a forma de chamar ele é: }  NomeDaClasse. nome_do_metodo( parametros ).deliver }  Como em: }  UsuariosMailer. registro( usuario ).deliver }  Isso vai fazer com que o ActionMailer gere o texto do email e o envie para o destinatário definido;