Logging in with username using Devise with Rails 4

devise, ruby-on-rails-4

Solution

Remove `validatable` from the `User` model `devise` section - this option validates the presence, uniqueness and format of the email address. You'll have to manually add your own validations for password presence, confirmation and length, though.

Problem

I'm using Rails 4.0 and Devise 3.0.0.rc. I installed Devise with its defaults - i.e. sign up/in using your email address. However, I'd like the users to be able to sign up with a username instead of their email address. I've followed the railscasts in terms of which parameters to change, plus any advice I can find on here for things I might need to change for Rails 4. However, whenever I try to create a new user, I am getting the error 'email can't be blank'. Does anyone have an idea as to what is causing this, and how I can fix it? Thanks!! Code: application controller: ``` class ApplicationController < ActionController::Base # Prevent CSRF attacks by raising an exception. # For APIs, you may want to use :null_session instead. protect_from_forgery with: :exception before_filter :configure_permitted_parameters, if: :devise_controller? protected def configure_permitted_parameters devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:username, :password, :password_confirmation) } devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:username, :password, :remember_me) } end end ``` Sign in (sign up form is pretty much the same): ``` <%= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %> <div><%= f.label :username %><br /> <%= f.text_field :username, :autofocus => true %></div> ``` In devise.rb config: ``` config.authentication_keys = [ :username ] ``` users controller: ``` private # Use callbacks to share common setup or constraints between actions. def set_user @user = User.find(params[:id]) end # Never trust parameters from the scary internet, only allow the white list through. def user_params params.require(:user).permit(:first_name, :middle_names, :last_name, :date_of_birth, :gender, :line_1, :line_2, :line_3, :town, :county, :postcode, :contact_number, :email, :username, :password, :password_confirmation, :remember_me) end ``` user.rb: ``` protected def self.find_for_database_authentication(warden_conditions) conditions = warden_conditions.dup login = conditions.delete(:login) where(conditions).where(["lower(username) = :value", { :value => login.downcase }]).first end ```

Original source