creating an account with a username in devise

Hello, all. I have followed these links and have enabled a (current) user to login with a username:

I want to allow a user to sign up with a username but am getting these errors and don't know how to proceed. Notice the 'Email can't be blank' error, even though I'm not wanting to accept an email for authentication. It also doesn't recognize that I entered a password or that they matched (even though they did):

Sign up 3 errors prohibited this user from being saved: Email can't be blank Password can't be blank Password confirmation doesn't match Password

Please see attached devise view new.html.erb and devise model user.rb

Please let me know if you require any further information. Any help would be greatly appreciated. Thanks.

Attachments: http://www.ruby-forum.com/attachment/8539/new.html.erb http://www.ruby-forum.com/attachment/8540/user.rb

I want to allow a user to sign up with a username but am getting these errors and don't know how to proceed. Notice the 'Email can't be blank' error, even though I'm not wanting to accept an email for authentication.

Did you remember to set "config.authentication_keys = [:username]" in the initializer? Show us at least the non-commented-out lines.

It also doesn't recognize that I entered a password or that they matched (even though they did):

That sounds like you may be pulling out the wrong part of the params. Can you show us the controller action and logged params? Or are you just using the default Devise controllers?

-Dave

Did you remember to set "config.authentication_keys = [:username]" in the initializer? Show us at least the non-commented-out lines.

$ grep -v \# config/initializers/devise.rb |grep . Devise.setup do |config|   config.mailer_sender = "password_reset@gloryhouseofprayer.com"   require 'devise/orm/active_record'   config.case_insensitive_keys = [ :username ]   config.strip_whitespace_keys = [ :username ]   config.stretches = Rails.env.test? ? 1 : 10   config.use_salt_as_remember_token = true   config.timeout_in = 30.minutes   config.reset_password_within = 2.hours   config.sign_out_via = :get   config.authentication_keys = [ :username ]   config.reset_password_keys = [ :username ]   config.confirmation_keys = [ :username ] end

That sounds like you may be pulling out the wrong part of the params. Can you show us the controller action and logged params? Or are you just using the default Devise controllers?

I apologize if I'm not following you, because I'm new to Ruby on Rails, but Devise didn't install any Controller, nor did it add anything to the default app/controller/application_controller.rb. So, I assume I'm using the default. However I did add an entry to my application's controller so I could authenticate before going to any page:

$ cat app/controllers/my_app_controller.rb class MyAppController < ApplicationController   before_filter :authenticate_user! ...

When I was looking through the logs (to respond to your "logged params" question I found this error: "Started POST "/users" for 127.0.0.1 at 2013-06-25 19:29:41 -0400 Processing by Devise::RegistrationsController#create as HTML   Parameters: {"utf8"=>"✓", "authenticity_token"=>"tltbt2w5FkZQbkbLqYaZIPiqk3J7VsdQIvKWFDCYLAs=", "user"=>{"firstname"=>"bob", "lastname"=>"smith", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"Sign up"} WARNING: Can't mass-assign protected attributes for User: password"

So, I googled it and saw references to removing the "attr_protected :password" from the model (user.rb).

I did that and now only get the "Email can't be blank" error when trying to sign up a user.

Here are the logs I get from rack when submitting the 'sign up' form:

Started POST "/users" for 127.0.0.1 at 2013-06-25 19:50:18 -0400 Processing by Devise::RegistrationsController#create as HTML   Parameters: {"utf8"=>"✓", "authenticity_token"=>"tltbt2w5FkZQbkbLqYaZIPiqk3J7VsdQIvKWFDCYLAs=", "user"=>{"firstname"=>"bob", "lastname"=>"smith", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"Sign up"}    (0.1ms) begin transaction    (0.1ms) rollback transaction   Rendered devise/shared/_links.erb (0.3ms)   Rendered devise/registrations/new.html.erb within layouts/application (3.6ms) Completed 200 OK in 97ms (Views: 10.8ms | ActiveRecord: 0.2ms)

Started GET "/assets/application.css?body=1" for 127.0.0.1 at 2013-06-25 19:50:18 -0400 [2013-06-25 19:50:18] WARN Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true

Started GET "/assets/bootstrap_and_overrides.css?body=1" for 127.0.0.1 at 2013-06-25 19:50:18 -0400 [2013-06-25 19:50:18] WARN Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true

Started GET "/assets/jquery.js?body=1" for 127.0.0.1 at 2013-06-25 19:50:18 -0400 [2013-06-25 19:50:18] WARN Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true

Started GET "/assets/jquery_ujs.js?body=1" for 127.0.0.1 at 2013-06-25 19:50:18 -0400 [2013-06-25 19:50:18] WARN Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true

Started GET "/assets/twitter/bootstrap/bootstrap-transition.js?body=1" for 127.0.0.1 at 2013-06-25 19:50:18 -0400 [2013-06-25 19:50:18] WARN Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true

Started GET "/assets/twitter/bootstrap/bootstrap-alert.js?body=1" for 127.0.0.1 at 2013-06-25 19:50:18 -0400 [2013-06-25 19:50:18] WARN Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true

Started GET "/assets/twitter/bootstrap/bootstrap-modal.js?body=1" for 127.0.0.1 at 2013-06-25 19:50:18 -0400 [2013-06-25 19:50:18] WARN Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true

Started GET "/assets/twitter/bootstrap/bootstrap-dropdown.js?body=1" for 127.0.0.1 at 2013-06-25 19:50:18 -0400 [2013-06-25 19:50:18] WARN Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true

Started GET "/assets/twitter/bootstrap/bootstrap-scrollspy.js?body=1" for 127.0.0.1 at 2013-06-25 19:50:18 -0400 [2013-06-25 19:50:18] WARN Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true

Started GET "/assets/twitter/bootstrap/bootstrap-tab.js?body=1" for 127.0.0.1 at 2013-06-25 19:50:18 -0400 [2013-06-25 19:50:18] WARN Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true

Started GET "/assets/twitter/bootstrap/bootstrap-tooltip.js?body=1" for 127.0.0.1 at 2013-06-25 19:50:18 -0400 [2013-06-25 19:50:18] WARN Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true

Started GET "/assets/twitter/bootstrap/bootstrap-popover.js?body=1" for 127.0.0.1 at 2013-06-25 19:50:18 -0400 [2013-06-25 19:50:18] WARN Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true

Started GET "/assets/twitter/bootstrap/bootstrap-button.js?body=1" for 127.0.0.1 at 2013-06-25 19:50:18 -0400 [2013-06-25 19:50:18] WARN Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true

Started GET "/assets/twitter/bootstrap/bootstrap-carousel.js?body=1" for 127.0.0.1 at 2013-06-25 19:50:18 -0400 [2013-06-25 19:50:18] WARN Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true

Started GET "/assets/twitter/bootstrap/bootstrap-collapse.js?body=1" for 127.0.0.1 at 2013-06-25 19:50:18 -0400 [2013-06-25 19:50:18] WARN Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true

Started GET "/assets/twitter/bootstrap/bootstrap-typeahead.js?body=1" for 127.0.0.1 at 2013-06-25 19:50:18 -0400 [2013-06-25 19:50:18] WARN Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true

Started GET "/assets/twitter/bootstrap/bootstrap-affix.js?body=1" for 127.0.0.1 at 2013-06-25 19:50:18 -0400 [2013-06-25 19:50:18] WARN Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true

Started GET "/assets/twitter/bootstrap.js?body=1" for 127.0.0.1 at 2013-06-25 19:50:18 -0400 [2013-06-25 19:50:18] WARN Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true

Started GET "/assets/turbolinks.js?body=1" for 127.0.0.1 at 2013-06-25 19:50:18 -0400 [2013-06-25 19:50:18] WARN Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true

Started GET "/assets/bootstrap.js?body=1" for 127.0.0.1 at 2013-06-25 19:50:18 -0400 [2013-06-25 19:50:18] WARN Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true

Started GET "/assets/prayer_requests.js?body=1" for 127.0.0.1 at 2013-06-25 19:50:18 -0400 [2013-06-25 19:50:18] WARN Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true

Started GET "/assets/application.js?body=1" for 127.0.0.1 at 2013-06-25 19:50:18 -0400 [2013-06-25 19:50:18] WARN Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true

Did you remember to set "config.authentication_keys = [:username]" in the initializer? Show us at least the non-commented-out lines.

$ grep -v \# config/initializers/devise.rb |grep .

Ah, we're obviously not dealing with a total programming-newbie here! :slight_smile:

  config.case_insensitive_keys = [ :username ]   config.strip_whitespace_keys = [ :username ]

...

  config.authentication_keys = [ :username ]   config.reset_password_keys = [ :username ]   config.confirmation_keys = [ :username ]

Okay, so far so good. Just to be sure, I compared it with one of my apps that uses username to log in, and the only other mention of username I had was config.unlock_keys (which you might not be using at all).

That sounds like you may be pulling out the wrong part of the params. Can you show us the controller action and logged params? Or are you just using the default Devise controllers?

I apologize if I'm not following you, because I'm new to Ruby on Rails, but Devise didn't install any Controller,

Actually, it does, just not placed in with your own controllers. In its own directory, it has controllers and views and so on. Gems provide Rails additional places to find such things. Some, such as Devise, also let you install stuff into your app's code dirs so that you can mess with them. (I'm guessing you did that with its views, in order to make it ask for first and last name instead of email.) Some don't, and are meant to run strictly out of their own dirs (modulo the configuration initializer).

I assume I'm using the default.

I'd agree.

However I did add an entry to my application's controller so I could authenticate before going to any page:

$ cat app/controllers/my_app_controller.rb class MyAppController < ApplicationController   before_filter :authenticate_user!

That should be fine.

When I was looking through the logs (to respond to your "logged params" question I found this error:

The rest of it looks good, confirming you're sending the right stuff to the right place.

WARNING: Can't mass-assign protected attributes for User: password"

So, I googled it and saw references to removing the "attr_protected :password" from the model (user.rb).

Yes, that's fairly important to understand. Another idea, though, is to get a bit ahead of the curve, and use Rails 4 with its "strong parameters". 4 was just released today, so it's now officially stable so you can build with it confidently. Also, if you're trying to get actual paid work in it, it's new enough that the competition will have some struggles too, which evens the playing field a bit against grizzled veterans like me. Oh, wait, never mind, stick with Rails 3, better yet go check out Rails 2, pay no attention to the release no longer behind the curtain.... :wink:

I did that and now only get the "Email can't be blank" error when trying to sign up a user.

Ah, good progress.

Maybe there's still a validation looking for email in your User class? Can you post that?

You could also go on a "search and destroy" mission: find all mentions of email in your app and examine them to see if they could be the cause. (Do you know about the "ack" utility?)

Come to think of it, there's a much simpler possibility; it may sound stupid, but we've all done it. Maybe you didn't restart your Rails server after modifying Devise. You need to do that to make it reread the initializers, such as the one that tells Devise what fields to use as keys.

-Dave

first of all, thanks man for helping me, I really appreciate it!

Ah, we're obviously not dealing with a total programming-newbie here! :slight_smile:

:slight_smile: I said I was new to Ruby, not to programming. Started with Qbasic on my commodore back in 1995 when I was 10. I know Assembly, C/C++, Python, Shell, PHP. But I digress....

Actually, it does, just not placed in with your own controllers. In its own directory, it has controllers and views and so on. Gems provide Rails additional places to find such things. Some, such as Devise, also let you install stuff into your app's code dirs so that you can mess with them.

Here's what I ran to install devise: rails generate devise:install rails generate devise user rails generate devise:views

(I'm guessing you did that with its views, in order to make it ask for first and last name instead of email.)

Nope, I edited that myself because I couldn't find anything anywhere.

parameters". 4 was just released today

I am using rails 4: $ rails -v Rails 4.0.0.rc2

Also, if you're trying to get actual paid work in it

Ha! I better not be, my resume would read: "I googled stuff!"

Actually I want to get this (personal) project done and figured I'd go back and learn why I did what I did and why it worked later. This goes against everything in me but I simply don't have the time (right now) to dedicate a month to fully learning ruby on rails before getting this project done.

Maybe there's still a validation looking for email in your User class? Can you post that?

$ grep -v \# app/models/user.rb |grep . class User < ActiveRecord::Base   devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :authentication_keys => [:username]   validates_presence_of :firstname, :lastname, :unique => true   after_validation :createUsername   attr_accessible :username, :password, :password_confirmation, :remember_me, :firstname, :lastname   def createUsername     firstnamePart=self.firstname[0,1].downcase     lastnamePart=self.lastname[0,5].downcase     username=lastnamePart + firstnamePart     count=0     while username.length != 7       username=username + count.to_s       count +=1     end     self.username=username   end   def self.find_first_by_auth_conditions(warden_conditions)       conditions = warden_conditions.dup       if login = conditions.delete(:login)         where(conditions).where(["lower(username) = :value OR lower(email) = :value", { :value => login.downcase }]).first       else         where(conditions).first       end     end end

You could also go on a "search and destroy" mission: find all mentions of email in your app and examine them to see if they could be the cause.

$ grep -ri email *|egrep -v "#|log" app/views/devise/mailer/unlock_instructions.html.erb:<p>Hello <%= @resource.email %>!</p> app/views/devise/mailer/confirmation_instructions.html.erb:<p>Welcome <%= @resource.email %>!</p> app/views/devise/mailer/reset_password_instructions.html.erb:<p>Hello <%= @resource.email %>!</p> app/views/devise/mailer/reset_password_instructions.html.erb:<p>If you didn't request this, please ignore this email.</p> config/locales/devise.en.yml: send_instructions: 'You will receive an email with instructions about how to reset your password in a few minutes.' config/locales/devise.en.yml: send_instructions: 'You will receive an email with instructions about how to confirm your account in a few minutes.' config/locales/devise.en.yml: send_paranoid_instructions: 'If your e-mail exists on our database, you will receive an email with instructions about how to confirm your account in a few minutes.' config/locales/devise.en.yml: send_instructions: 'You will receive an email with instructions about how to unlock your account in a few minutes.' config/locales/devise.en.yml: send_paranoid_instructions: 'If your account exists, you will receive an email with instructions about how to unlock it in a few minutes.' Binary file db/development.sqlite3 matches db/schema.rb: t.string "email", default: "", null: false db/schema.rb: add_index "users", ["email"], name: "index_users_on_email", unique: true Binary file tmp/cache/assets/development/sprockets/d585a06e2ee6203ccb04c8b84150d14d matches Binary file tmp/cache/assets/development/sprockets/13fe41fee1fe35b49d145bcc06610705 matches Binary file tmp/cache/assets/development/sprockets/8c2b061e379a23e7c4d207adcf992462 matches Binary file tmp/cache/assets/development/sprockets/357970feca3ac29060c1e3861e2c0953 matches Binary file tmp/cache/assets/development/sprockets/b7fc7a50cc3464d16f378714639f14e2 matches

(Do you know about the "ack" utility?)

a rails utility? Nope, never heard of an 'ack' utility.

Maybe you didn't restart your Rails server after modifying Devise.

I've only done that 500 times. Really, after every single change I made I restarted rack, just in case.

that 'email' reference search looked lousy posting it directly, so here it is in an attached file.

Attachments: http://www.ruby-forum.com/attachment/8541/rails_app_email_references