3
votes

When I went to generate the devise views I wanted to modify the new registration page to capture more than just the email & password. My devise user model has fields like first name last name address and many more.

This is my form as of right now

<div class="row">
    <div class="col-sm-6 col-sm-offset-3">
        <h2>Sign up</h2>

<%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name), html: {class:'form-horizontal'}) do |f| %>
  <%= f.error_notification %>

    <div class="row">
        <%= f.input :email, required: true, autofocus: true %>
        <%= f.input :password, required: true %>
        <%= f.input :password_confirmation, required: true %>
    </div>
    <div class="row">
        <h2>About yourself</h2>
        <%= f.input :first_name, required: true %>
        <%= f.input :last_name, required: true %>
        <%= f.input :phone, required: true %>
        <%= f.input :addressL1, label: 'Address Line 1', required: true %>
        <%= f.input :addressL2, label: 'Address Line 2' %>
        <%= f.input :city, required: true %>
        <%= f.input :postalCode, required: true %>
        <%= f.input :province, required: true, collection: provinces, prompt: '<-- select -->' %>
    </div>

    <%= f.button :submit, "Sign up" %>

<% end %>

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

    </div>
</div>

How come when I submit the form only email and password get saved?

2
Lets see the log to see what is going on. Have you whitelisted the attributes?DDDD
Can you show your devise model as well?rb512

2 Answers

10
votes

Take a look at the Rails and Devise example application from the RailsApps project. I've also written a Rails Devise Tutorial that explains in detail how to add attributes to a Devise sign-up form.

You need to tell Devise that the additional attributes are "permitted parameters." Otherwise, the "strong parameters" security measure introduced in Rails 4.0 will simply drop the unpermitted parameters, creating a new user without setting the additional attributes.

There are three different ways to add permitted parameters in Devise:

  • override the default Devise registrations controller
  • add code to the Application controller
  • add an initializer file

The third way is the simplest. Add a file to your application:

# config/initializers/devise_permitted_parameters.rb

module DevisePermittedParameters
  extend ActiveSupport::Concern

  included do
    before_filter :configure_permitted_parameters
  end

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.for(:sign_up) << :first_name << :last_name << :phone << :addressL1 << :addressL2 << :city << :postalCode << :province
    devise_parameter_sanitizer.for(:account_update) << :first_name << :last_name << :phone << :addressL1 << :addressL2 << :city << :postalCode << :province
  end

end

DeviseController.send :include, DevisePermittedParameters

You can see that you pass the additional parameters to the devise_parameter_sanitizer method. These two lines tell Devise to accommodate additional attributes. If you want to add other attributes, or different attributes, modify these two statements.

The rest of the file implements a Rails concern. Concerns are modules that can be mixed into models and controllers to add shared code. Typically, these modules go in a app/controllers/concerns/ folder and are added to a controller with an include keyword. In this case, we use the Ruby send method to add our mixin to the DeviseController object, adding include DevisePermittedParameters to the DeviseController without actually editing the code.

After making these changes and trying the application, you should see the additional attributes in the user record. If it doesn't work, show us more of your code, including the user model and controller.

4
votes

In Rails 4 with the introduction of Strong Parameters, parameter sanitization was moved from model to controller level. This needs to be taken care of when adding additional fields (other than email and password) to a devise model. Currently, you have not done this that is why only email and password fields are getting saved in the database and NOT the additional fields.

You can resolve this by permitting the additional attributes of devise model via a before_action in ApplicationController.

class ApplicationController < ActionController::Base
  #... 
  ## Add this before_action
  before_action :configure_permitted_parameters, if: :devise_controller?

  protected

  def configure_permitted_parameters
    ## To permit attributes while registration i.e. sign up (app/views/devise/registrations/new.html.erb)
    devise_parameter_sanitizer.for(:sign_up) << :attrb1 << :attrb2 

    ## To permit attributes while editing a registration (app/views/devise/registrations/edit.html.erb)
    devise_parameter_sanitizer.for(:account_update) << :attrb1 << :attrb2
  end
end

where,

you need to replace :attrb1, :attrb2 with the name of attributes that you want to permit. For example :first_name, :last_name and so on.

Refer to Devise: Strong Parameters for additional information.