1 分鐘閱讀

本文使用 Ruby 2.3.1 / Rails 5.0.0

建立 Username

rails generate migration add_username_to_users username:string:uniq
rails db:migrate

設定 Strong parameters

# [path] application_controller.rb
class ApplicationController < ActionController::Base
  before_action :configure_permitted_parameters, if: :devise_controller?

  protected

  def configure_permitted_parameters
    added_attrs = [:username, :email, :password, :password_confirmation, :remember_me]
    devise_parameter_sanitizer.permit :sign_up, keys: added_attrs
    devise_parameter_sanitizer.permit :account_update, keys: added_attrs
  end
end

在 User 裡面建立一個虛擬屬性: login

# [path] User.rb
  def login=(login)
    @login = login
  end

  def login
    @login || self.username || self.email
  end

告訴 Devise 要使用 :login 當作 authentication_keys

# [path] config/initializers/devise.rb
config.authentication_keys = [ :login ]

Override Devise 的 find_for_database_authentication method

# [path] User.rb
    def self.find_for_database_authentication(warden_conditions)
      conditions = warden_conditions.dup
      if login = conditions.delete(:login)
        where(conditions.to_h).where(["lower(username) = :value OR lower(email) = :value", { :value => login.downcase }]).first
      elsif conditions.has_key?(:username) || conditions.has_key?(:email)
        where(conditions.to_h).first
      end
    end

加入驗證機制

# [path] User.rb
  validates_format_of :username, with: /^[a-zA-Z0-9_\.]*$/, :multiline => true
  validates :username, :presence => true, :uniqueness => { :case_sensitive => false }

產生View畫面

第一種方式:(路徑會在/view/devise/之下)

rails g devise:views 

第二種方式:(路徑會在/view/user/之下,但要去devise調整scoped_views參數才會生效)

rails g devise:views user
# [path] config/initializers/devise.rb
config.scoped_views = true

調整 View 畫面

# [path] sessions/new.html.erb
<div class="form-group">
  <%= f.label :login, "Username" %><br />
  <%= f.text_field :login, autofocus: true, class: "form-control",  placeholder: "" %>
</div>
# [path] registrations/new.html.erb
<div class="form-group">
  <%= f.label :username %><br />
  <%= f.text_field :username, autofocus: true  %>
</div>
# [path] registrations/edit.html.erb
<div class="form-group">
  <%= f.label :username %><br />
  <%= f.text_field :username, autofocus: true  %>
</div>

參考

  1. https://github.com/plataformatec/devise/wiki/How-To:-Allow-users-to-sign-in-using-their-username-or-email-address

更新時間:

留言