The following blog post contains material either currently found or soon to be incorporated into my new book, "Easy Active Record for Rails Developers". Among many other topics, you'll learn about model generation, migrations, validations, associations, scopes, joins, includes, forms integration, nested forms, and model testing with RSpec and FactoryGirl. The book is now available, head over to this website's home page to learn more.


Easy Active Record for Rails Developers readers learn the many ins and outs of building database-driven Ruby on Rails applications by loosely following along with the development of a location-based web application geared towards retro arcade aficionados. The companion project is called ArcadeNomad, and among the many features it demonstrates is Devise integration. ArcadeNomad visitors can optionally create an account, login, logout, recover a lost password, change a password, and update account attributes.

ArcadeNomad’s Devise integration is pretty vanilla, although I did override the default Devise templates in order to stylize the forms using Bootstrap. For instance, you’ll notice the sign in form looks quite a bit more attractive than the default version provided by Devise.

Additionally, I wanted to demonstrate the ability to gather additional profile attributes beyond those Devise gathers by default (only the user’s e-mail address and password), and so have taken the steps necessary to override the profile management form in order to additionally gather the user’s name (see below screenshot). Of course, additional details could also be gathered, such as the user’s city, state, or date-of-birth.

ArcadeNomad's account profile form

Let’s work through an example demonstrating how this was accomplished. Begin by adding the user’s name to the users table, accomplished through a migration:

$ rails g migration addNameToUsers name:string
  invoke  active_record
  create    db/migrate/20140909130956_add_name_to_users.rb

Next, incorporate the name column into the users table by running the migration:

$ rake db:migrate
  == 20140909130435 AddNameToUsers: migrating ========
  -- add_column(:users, :name, :string)
     -> 0.0249s
  == 20140909130435 AddNameToUsers: migrated (0.0250s) ========

Next, open the app/views/devise/registrations/edit.html.erb view and add the appropriate field just as you did in Chapter 5:

<div class="form-group">
  <%= f.label :name %>
  <%= f.text_field :name, class: 'form-control' %>
</div>

If you reload /users/edit you’ll see the new field. However, if you enter a name, submit the form, and subsequently return to /users/edit, you’ll see the name has not been persisted. This is because Devise does not for security reasons simply allow updates to any attribute other than those it specifically declares as being safe. There are a number of different solutions to informing Devise of your wish to update another attribute, however in my experience the easiest approach is to add the following code to your project’s /app/controllers/application_controller.rb:

before_filter :configure_devise_parameters, if: :devise_controller?

protected
def configure_devise_parameters
  devise_parameter_sanitizer.for(:account_update) << :name
end

This tells Rails to execute the method configure_devise_parameters if the executing controller is Devise-related. In doing so, we’ll add the name attribute to the Devise parameter sanitizer when updating an account. With this complete, try completing the account management form again and this time you’ll see the name has indeed been saved!

Comments