2

I've tried everything I can find, including what is in the Devise README (https://github.com/plataformatec/devise#strong-parameters), this more descriptive take on the README (http://blog.12spokes.com/web-design-development/adding-custom-fields-to-your-devise-user-model-in-rails-4/comment-page-1/#comment-26217), and every answer I find on StackOverflow seems consistent with these 2 solutions. All these solutions result in the same error: 2 errors prohibited this user from being saved: - Email can't be blank - Password can't be blank

I also tried including gem 'protected_attributes' in the gemfile and running bundle so that I could use attr_accessible rather than strong parameters. With this approach, it appeared that I was able to save the user okay, but none of my fields, custom or otherwise, actually persisted. They all remained nil. I also tried reverting devise back to a previous version where attr_accessible was used rather than strong parameters and that resulted in the same issue where nothing persisted.

I'm at a complete standstill with this at the moment so any ideas on other solutions that may work would be greatly appreciated... Thanks in advance!

EDIT: Here's my application controller:

class ApplicationController < ActionController::Base
  before_filter :configure_permitted_parameters, if: :devise_controller?

  protected

  def configure_permitted_parameters
         devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:profile_name, :email, :password) }
         devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:first_name, :last_name, :profile_name, :email, :password, :password_confirmation) }
         devise_parameter_sanitizer.for(:account_update) { |u| u.permit(:first_name, :last_name, :profile_name, :email, :password, :password_confirmation, :current_password) }
  end


  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  protect_from_forgery with: :exception

end
Jake
  • 23
  • 5
  • what does your user controller look like? Have you added a method for strong parameters in the controller? – Jason Carty Oct 01 '13 at 13:58
  • I'm passing the strong parameters to my user model through my application controller. I added my code to my original question. Thanks for your help! Please let me know if you need any other info. – Jake Oct 02 '13 at 02:22
  • This tutorial helped me with these sorts of problems. In case it helps anyone else as well: http://www.jacopretorius.net/2014/03/adding-custom-fields-to-your-devise-user-model-in-rails-4.html – kingsfoil Oct 10 '14 at 16:20

2 Answers2

3

I have created an sample app and this works for me.

user.rb

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
end

in devise registrations new.html.erb view

<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
  <%= devise_error_messages! %>

  <div><%= f.label :firstname %><br />
  <%= f.text_field :firstname, :autofocus => true %></div>

  <div><%= f.label :lastname %><br />
  <%= f.text_field :lastname %></div>

  <div><%= f.label :email %><br />
  <%= f.email_field :email, :autofocus => true %></div>

  <div><%= f.label :password %><br />
  <%= f.password_field :password %></div>

  <div><%= f.label :password_confirmation %><br />
  <%= f.password_field :password_confirmation %></div>

  <div><%= f.submit "Sign up" %></div>
<% end %>

<%= render "devise/shared/links" %>

and in devise_create_user migration

class DeviseCreateUsers < ActiveRecord::Migration
  def change
    create_table(:users) do |t|
      ## Database authenticatable
      t.string :firstname
      t.string :lastname
      t.string :email,              :null => false, :default => ""
      t.string :encrypted_password, :null => false, :default => ""

      ## Recoverable
      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      ## Rememberable
      t.datetime :remember_created_at

      ## Trackable
      t.integer  :sign_in_count, :default => 0, :null => false
      t.datetime :current_sign_in_at
      t.datetime :last_sign_in_at
      t.string   :current_sign_in_ip
      t.string   :last_sign_in_ip

      ## Confirmable
      # t.string   :confirmation_token
      # t.datetime :confirmed_at
      # t.datetime :confirmation_sent_at
      # t.string   :unconfirmed_email # Only if using reconfirmable

      ## Lockable
      # t.integer  :failed_attempts, :default => 0, :null => false # Only if lock strategy is :failed_attempts
      # t.string   :unlock_token # Only if unlock strategy is :email or :both
      # t.datetime :locked_at

      t.string :authentication_token


      t.timestamps
    end

    add_index :users, :email,                :unique => true
    add_index :users, :reset_password_token, :unique => true
    # add_index :users, :confirmation_token,   :unique => true
    # add_index :users, :unlock_token,         :unique => true
  end
end

in routes

Topic::Application.routes.draw do

  devise_for :users#, controllers: { registrations: "registrations" }

  resources :maintopics do
    resources :subtopics
  end
end

and in application controller

class ApplicationController < ActionController::Base
  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.

  before_filter :configure_permitted_parameters, if: :devise_controller?

  def configure_permitted_parameters
   devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:firstname, :lastname, :email, :password, :password_confirmation) }
  end

  protect_from_forgery with: :exception

end

In your case i think there is an problem of parameters so create new registration controller and add following code in it to check the parameters value.

class RegistrationsController < Devise::RegistrationsController

  def create
    raise params.inspect
  end
end

in routes file replace existing with following line.

devise_for :users, controllers: { registrations: "registrations" }
Amit Sharma
  • 3,427
  • 2
  • 15
  • 20
  • Hi Amit, this looks very similar to what I'm already doing in my application controller. Please see my edited question above. This currently isn't working for me. Thanks for your help, though! Please let me know if you need any other info. – Jake Oct 02 '13 at 02:29
  • you are getting this error `2 errors prohibited this user from being saved: - Email can't be blank - Password can't be blank` because devise unable to get these parameters. – Amit Sharma Oct 02 '13 at 07:08
  • Wow, thanks for the detailed response and so quick, too! I am going to try this out when I get home tonight and hopefully it works - I'll let you know what I find. Thanks again! – Jake Oct 02 '13 at 16:14
  • Hey Amit, I tried your suggestions and I am now running into the following error on my /users/sign_up page - Routing Error: uninitialized constant RegistrationsController. Any ideas? – Jake Oct 03 '13 at 01:22
  • @Jake have you replaced existing line with this line `devise_for :users, controllers: { registrations: "registrations" }` in routes file after adding registration controller. – Amit Sharma Oct 03 '13 at 07:10
  • Hey Amit, I did replace that line. I decided to re-build the application from scratch, though. Your solution for the application controller worked for me the second time around and I didn't need to add the update to the routes - I have no idea what happened to the first app. Maybe it had something to do with devise since it was a release candidate and they released 3.1.1 just the other day, or maybe installing simple_form caused the issue with non-persisting fields. I am going to play around with it some more tonight and see if I can figure out why it happened. Thanks for all your help!! – Jake Oct 03 '13 at 16:12
0

You also need to add a strong parmeters method to your user controller:

def update
  person = current_account.people.find(params[:id])
  person.update_attributes!(person_params)
  redirect_to person
end

private

def person_params
  params.require(:person).permit(:name, :age)
end
Jason Carty
  • 1,247
  • 2
  • 13
  • 17
  • Thanks for the quick response Jason! I am going to try this out along with Amit's suggestions when I get home from work tonight. I'll let you know what I find. Thanks again! – Jake Oct 02 '13 at 16:15
  • Hey Jason, just realized this is from the 12 spokes example I provided... but then the writer goes on to further specify: **Using this as an example, you might think that the way to enable the first_name and last_name fields on your user model would look something like this: def user_params params.require(:user).permit(:first_name, :last_name) end It’s a good assumption, but since we’re using Devise, it’s a bit trickier. To understand why, we need to look at how Devise implements parameter sanitization when strong parameters are in use.** His fix didn't work for me. Thanks! – Jake Oct 03 '13 at 01:56