Skip to content

Instantly share code, notes, and snippets.

@pifleo
Created April 5, 2012 10:32
Show Gist options
  • Save pifleo/2309833 to your computer and use it in GitHub Desktop.
Save pifleo/2309833 to your computer and use it in GitHub Desktop.
Rails - devise sign in by username or email - lib on user model
# How To: Allow users to sign in using their username or email address
# https://github.com/plataformatec/devise/wiki/How-To:-Allow-users-to-sign-in-using-their-username-or-email-address
# lib/devise_by_login.rb
# Extension of user model to add :login field on devise
module DeviseByLogin
def self.included(base)
base.class_eval do
# attr_accessible
attr_accessible :login
# Virtual attribute for authenticating by either username or email
# This is in addition to a real persisted field like 'username'
attr_accessor :login
# ---------- Devise - connexion by username or email ---------- #
protected
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
# 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
# ------------------------------------------------------------- #
end
end
end
-# app/views/devise/passwords/new.html.haml
%h3= t("devise.shared.forgot_password")
= form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :post }) do |f|
= devise_error_messages!
%div
= f.label :login
= f.text_field :login
%div.offset1= f.submit t("devise.passwords.send_reset_password_instructions")
= render "links"
-# app/views/devise/registrations/new.html.haml
%h3= t("devise.shared.sign_up")
= form_for(resource, :as => resource_name, :url => (resource && resource.usertype) ? "signup_#{resource.usertype}" : registration_path(resource_name)) do |f|
= devise_error_messages! if resource
%div
= f.label :username
= f.text_field :username
%div
= f.label :email
= f.email_field :email
%div
= f.label :password
= f.password_field :password
%div
= f.label :password_confirmation
= f.password_field :password_confirmation
%div.offset2= f.submit t("devise.shared.sign_up")
= render "links"
-# app/views/devise/sessions/new.html.haml
%h3= t("devise.shared.sign_in")
= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f|
%div
= f.label :login
= f.text_field :login
%div
= f.label :password
= f.password_field :password
- if devise_mapping.rememberable?
%div
= f.check_box :remember_me
= f.label :remember_me
%div.offset2= f.submit t("devise.shared.sign_in")
= render "links"
-# app/views/devise/sessions/new.html.haml
%h3= t("devise.shared.sign_in")
= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f|
%div
= f.label :login
= f.text_field :login
%div
= f.label :password
= f.password_field :password
- if devise_mapping.rememberable?
%div
= f.check_box :remember_me
= f.label :remember_me
%div.offset2= f.submit t("devise.shared.sign_in")
= render "links"
-# app/views/devise/sessions/new.html.haml
%h3= t("devise.shared.sign_in")
= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f|
%div
= f.label :login
= f.text_field :login
%div
= f.label :password
= f.password_field :password
- if devise_mapping.rememberable?
%div
= f.check_box :remember_me
= f.label :remember_me
%div.offset2= f.submit t("devise.shared.sign_in")
= render "links"
# app/models/user.rb
class User < ActiveRecord::Base
include DeviseByLogin # lib/devise_by_login.rb
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:token_authenticatable, :lockable, :timeoutable, :omniauthable, :confirmable #, :encryptable
...
# attr_accessible
# Setup accessible (or protected) attributes for your model
attr_accessible :username, :name, :first_name, :email, :password, :password_confirmation,
:remember_me, :terms_of_service #, ...
scope :confirmed, where('confirmed_at IS NOT NULL')
scope :unlocked, where('locked_at IS NULL')
scope :locked, where('locked_at IS NOT NULL')
scope :admin, where('admin')
...
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment