Search code examples
ruby-on-railsruby-on-rails-3ruby-on-rails-4devisestrong-parameters

Allowing a nested attribute for a User with Devise in Rails 4


I'm upgrading from Rails 3.2 to 4.0 and am using Devise for my User model. Previously I had attr_accessible attributes in my User model:

attr_accessible :username, :first_name, :last_name, :email, :password, :password_confirmation, :remember_me

Now according to the Devise documentation for strong parameters, I have to do the following in my application_controller.rb in a before_filter method:

devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:username, :first_name, :last_name, :email, :password, :password_confirmation, :remember_me) }
devise_parameter_sanitizer.for(:account_update) { |u| u.permit(:username, :first_name, :last_name, :email, :password, :password_confirmation, :remember_me, :current_password) }

That seems fine, but I also have an accepts_nested_attributes_for in my User model:

accepts_nested_attributes_for :staff, reject_if: :new_record?

How do I specify that in my devise_parameter_sanitizer.for(:account_update)? This is not clear to me.

UPDATE: I tried the following:

devise_parameter_sanitizer.for(:account_update) { |u| u.permit(:username, :first_name, :last_name, :email, :password, :password_confirmation, :remember_me, :current_password, staff_attributes: [:notification_email]) }

In particular, I added staff_attributes: [:notification_email] as a parameter to the permit method. 3 major problems happened when I simply saved a user edit form without making any changes:

  1. Error displayed: "Staff notification email has already been taken" (I have validates :notification_email, uniqueness: true, allow_nil: true in the Staff model)
  2. Error displayed: "Staff project can't be blank" (I have validates_presence_of :project_id in the Staff model)
  3. Even though I received those 2 errors, the staff model associated with the user was wiped out, all attributes were set to nil except the notification_email. This included the user_id field, so the staff object was no longer connected to the user.

Solution

  • These are nested attributes, so you need to add them in following way:

    devise_parameter_sanitizer.for(:sign_up) { |u|
      u.permit(:username, :staff_attributes => [:name, :position, :etc]) 
    }