Rails 4.0 and Devise With Strong Params and Custom Fields

Chris Oliver

August 18, 2013

As we all begin transitioning to Rails 4.0 and strong_params there are going to be a fair amount of changes to our gems and other integrations. Since the attr_accessible functionality no longer exists inside our models, we need to move this into the controllers that are responding to our web forms.

Devise, one of the common authentication gems, provides a reasonably easy way to accept extra fields as part of registration. The first thing we do is add the extra fields to the model in the database. I'm assuming you know how to add a migration to create these fields, so we will skip right updating the view.

Just as usual, we generate the Devise views by running rails g devise:views. Hopping into app/views/devise/registrations/new.html.erb we can add our extra fields. In this example I'm just going to show a snippet of the form fields I'm adding. I'm also using Formtastic to generate a lot of the HTML around the fields for Bootstrap automatically. Formtastic provides the semantic_form_for and f.input methods you see in this example.

<%= semantic_form_for(resource, :as => resource_name, :url => registration_path(resource_name), html: {class: "form-vertical"}) do |f| %>
  <%= f.input :full_name %>
  <%= f.input :phone %>
  <%= f.input :email %>
  <%= f.input :password %>
  <%= f.input :password_confirmation %>
<% end %>

You can also write regular f.text_field fields and a regular form_for, we just need to make sure that the fields are rendering on the page. Now when you submit this, it is going to send over the data but those fields won't be permitted so your users will be missing data that was submitted.

Devise allows you to override the strong_params implementation from the ApplicationController pretty easily. The idea is that you put it into a before_filter to check to see if the current controller processing the request is one from Devise. If it is, then we override the parameters that are allowed.

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(:email, :password, :password_confirmation, :full_name, :phone) }
  end
end

And surprisingly, that's all you have to do. Adding a couple lines into your application_controller.rb isn't such a bad thing and it certainly makes for a more flexible and secure implementation than attr_accessible did. That's all for today!

Want to learn more about Devise? Check out the Rails Gems Foundation Course

P.S. You might enjoy following me on Twitter.


Comments