//
você está lendo...
devise, gem, Linux, master-detail, rails, Rails 3.1, Rails 3.2.1, ruby on rails, ubuntu

Autenticação – Permitir login com nome de usuário ou email

I – Introdução

II – Principais tecnologias usadas neste artigo

  • Linux Ubuntu 11.10
  • Ruby 1.9.2
  • Rails 3.2.1
  • gem Devise 2.0

III – O que não precisamos instalar

IV – O que precisa ser feito antes

V – Sequência de passos para implementação

Passo 01 – Entre na aplicação que criamos anteriormente

$ cd service_desk

Passo 02 – Corrigir mensagens

  • Para que o app tenha menos código e fique mais DRY (Don’t repeat yourself), vamos corrigir duas views.
  • Em app/views/tickets/show.html.erb, retire a seguinte linha
<p id="notice"><%= notice %></p>
  • Em app/views/layouts/application.html.erb, modifique a “section main” para que fique da seguinte maneira:
<section id="main">
   <p class="notice"><%= notice %></p>
   <p class="alert"><%= alert %></p>
   <%= yield %>
</section>

Passo 03 – Inclua a coluna username na tabela de usuários (Users)

  • A coluna username será única (uniq) na tabela Users.
  • A migration irá gerar um índice na mesma tabela Users, para otimizar os acessos pela chave username.
$ rails g migration add_username_to_users username:string:uniq
$ bundle exec rake db:migrate

Passo 04 – Gere as views do Devise

  • Para incluir o campo username, que terá a label “login” nas views do Devise, é necessário personalizar as mesmas views.
  • Vamos, agora, gerar todas a views do Devise para que seja possível personalizar as telas de registro de usuário, de login de usuário, e tela de modificação de senha.
$ rails g devise:views
  • Veja abaixo que foram criados a pasta “devise” e as pastas e arquivos (views) do Devise.
$ tree app/views/devise/
app/views/devise/
├── confirmations
│   └── new.html.erb
├── _links.erb
├── mailer
│   ├── confirmation_instructions.html.erb
│   ├── reset_password_instructions.html.erb
│   └── unlock_instructions.html.erb
├── passwords
│   ├── edit.html.erb
│   └── new.html.erb
├── registrations
│   ├── edit.html.erb
│   └── new.html.erb
├── sessions
│   └── new.html.erb
└── unlocks
    └── new.html.erb

6 directories, 11 files

Passo 05 – Modifique as views do Devise a seguir

  • Na view app/views/devise/sessions/new.html.erb:
<div><%= f.label :email %><br /> # delete essa linha
<%= f.email_field :email %></div> # delete essa linha
<div><%= f.label :login %><br /> # insira essa linha
<%= f.text_field :login %></div>  # insira essa linha
  • Na view app/views/devise/registrations/new.html.erb:
<div><%= f.label :username %><br /> # insira essa linha
<%= f.text_field :username %></div> # insira essa linha
<div><%= f.label :email %><br /> # mantenha essa linha
<%= f.email_field :email %></div> # mantenha essa linha
  • Na view app/views/devise/registrations/edit.html.erb:
<div><%= f.label :username %><br /> # insira essa linha
<%= f.text_field :username %></div> # insira essa linha
<div><%= f.label :email %><br /> # mantenha essa linha
<%= f.email_field :email %></div> # mantenha essa linha
  • Na view app/views/devise/passwords/new.html.erb:
<div><%= f.label :email %><br /> # delete essa linha
<%= f.email_field :email %></div> # delete essa linha
<div><%= f.label :login %><br /> # insira essa linha
<%= f.text_field :login %></div> # insira essa linha

Passo 06 – Modifique a label das views para que mostre “username or email” ao usuário

  • Modifique o arquivo /config/locales/en.yml para que fique parecido com o trecho abaixo:
en:
  hello: "Hello world"            

  activerecord:
    attributes:
      user:
        login: "Username or email"

Passo 07 – Indique ao Devise para que use :login no authentication_keys

  • Modifique o arquivo /config/initializers/devise.rb para que tenha:
config.authentication_keys = [ :login ]

Passo 08 – Agora várias alterações do model User serão necessárias

  • Modifique o arquivo /app/model/user.rb para que tenha:
attr_accessible :username, :login

# Virtual attribute for authenticating by either username or email
# This is in addition to a real persisted field like 'username'
attr_accessor :login

# Overwrite Devise’s find_for_database_authentication method
def self.find_for_database_authentication(warden_conditions)
   conditions = warden_conditions.dup
   login = conditions.delete(:login)
   where(conditions).where(["lower(username) = :value OR lower(email) = :value", { :value =>
     login.strip.downcase }]).first
end

protected

 # Attempt to find a user by it's email. If a record is found, send new
 # password instructions to it. If not user is found, returns a new user
 # with an email not found error.
 def self.send_reset_password_instructions(attributes={})
   recoverable = find_recoverable_or_initialize_with_errors(reset_password_keys, attributes, :not_found)
   recoverable.send_reset_password_instructions if recoverable.persisted?
   recoverable
 end 

 def self.find_recoverable_or_initialize_with_errors(required_attributes, attributes, error=:invalid)
   (case_insensitive_keys || []).each { |k| attributes[k].try(:downcase!) }

   attributes = attributes.slice(*required_attributes)
   attributes.delete_if { |key, value| value.blank? }

   if attributes.size == required_attributes.size
     if attributes.has_key?(:login)
        login = attributes[:login]
        record = find_record(login)
     else
       record = where(attributes).first
     end
   end  

   unless record
     record = new

     required_attributes.each do |key|
       value = attributes[key]
       record.send("#{key}=", value)
       record.errors.add(key, value.present? ? error : :blank)
     end
   end
   record
 end

 def self.find_record(login)
   where(["username = :value OR email = :value", { :value => login }]).first
 end

Passo 09 – Alimentar dados automaticamente no sistema

  • Vamos usar comandos de inserção de dados, dentro do arquivo “seed.rb”
  • Cada vez que alguém iniciar este projeto do zero, será possível inicia-lo com esses dados de exemplo.
  • Desta forma, teremos quatro usuários já cadastrados no sistema, todos com a senha 123456:
    • superuser
    • admin
    • user
    • user1
  • Modifique o arquivo /db/migrate/seeds.rb para que tenha:
superuser_user = User.create!(:username => 'superuser',
                              :email => 'superuser@example.com',
                              :password => '123456',
                              :password_confirmation => '123456',
                              :confirmed_at => Time.now )
admin_user = User.create!(:username => 'admin',
                          :email => 'admin@example.com',
                          :password => '123456',
                          :password_confirmation => '123456',
                          :confirmed_at => Time.now )
user_user = User.create!(:username => 'user',
                         :email => 'user@example.com',
                         :password => '123456',
                         :password_confirmation => '123456',
                         :confirmed_at => Time.now )
user1_user = User.create!(:username => 'user1',
                          :email => 'user1@example.com',
                          :password => '123456',
                          :password_confirmation => '123456',
                          :confirmed_at => Time.now )                               

# create ticket #1
tkt1 = Ticket.create!( ticket_number: "00001", title: "ticket number 00001" )
Task.create!( description: "task 001 of ticket 00001", ticket_id: tkt1.id )         

# create ticket #2
tkt2 = Ticket.create!( ticket_number: "00002", title: "ticket number 00002" )
Task.create!( description: "task 001 of ticket 00002", ticket_id: tkt2.id )
Task.create!( description: "task 002 of ticket 00002", ticket_id: tkt2.id )         

# create ticket #3
tkt3 = Ticket.create!( ticket_number: "00003", title: "ticket number 00003" )
Task.create!( description: "task 001 of ticket 00003", ticket_id: tkt3.id )
Task.create!( description: "task 002 of ticket 00003", ticket_id: tkt3.id )
Task.create!( description: "task 003 of ticket 00003", ticket_id: tkt3.id )
  • Para que o seed acima seja executado, execute o comando:
$ bundle exec rake db:seed

Passo 10 – Conferencia dos Models

  • Agora o seu model Ticket (app/model/ticket.rb) terá que ficar assim:
 class Ticket < ActiveRecord::Base
  has_many :tasks    validates :ticket_number, presence: true
  accepts_nested_attributes_for :tasks, :reject_if => proc { |a| a[:description].blank? }, allow_destroy:
 ...true
   attr_accessible :ticket_number, :title
 end
  • E seu model Task (app/model/task.rb) assim:
class Task < ActiveRecord::Base
  belongs_to :ticket
  attr_accessible :description, :ticket_id
end

Passo 11 – Execute a aplicação localmente

$ rails server

VI – Final Feliz

Pronto!
Fizemos o básico para que nosso app web aceite username ou o email do usuário.
Também criamos um arquivo “seed” que poderá ser usado para criar dados iniciais (inclusive usuários) de exemplo no sistema.

VII – Referências

  1. Instalação do Ruby On Rails 3.1.1 no Linux Ubuntu 11.10
  2. Ruby On Rails 3.1.3 no Linux Ubuntu 11.10: Iniciando um novo projeto – versão 2
  3. Aplicação “mestre detalhe” em Rails 3.2.1
  4. Autenticação em Ruby On Rails 3.2.1 com Devise
  5. How To: Allow users to sign in using their username or email address
About these ads

Discussão

Nenhum comentário ainda.

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

WordPress.com Logo

Você está comentando usando sua conta WordPress.com. Sair / Mudar )

Imagem do Twitter

Você está comentando usando sua conta Twitter. Sair / Mudar )

Foto do Facebook

Você está comentando usando sua conta Facebook. Sair / Mudar )

Conectando a %s

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Join 7 other followers

Categorias

My Links

fevereiro 2012
D S T Q Q S S
« jan    
 1234
567891011
12131415161718
19202122232425
26272829  
Seguir

Obtenha todo post novo entregue na sua caixa de entrada.

%d bloggers like this: