Don't touch Devise's defaults

At some point or another, you’ll probably want to customize Devise’s registration process. The stereotypical example is creating an additional record on signup: you’re registering Users and you want to give each user an Organization, or something like that. And it works pretty well: you can add an :organization_name field to the user registration form and create the organization during sign_up:

class RegistrationsController < Devise::RegistrationsController

# ...


def sign_up(resource_name, resource)
user = resource

# create an organization and associate it with the user
organization_name = params[:user][:organization_name]
Organization.create(name: organization_name, owner: user)

# Sign in the user
sign_in(resource_name, user)

But I believe that this approach should only be used as a last resort. If you want to run special logic during Devise’s registration process, you’ll open up a can of worms:

In Getting Real, Basecamp writes about letting software “push back”; that is, instead of fighting against software to make it bend to your whims, you bend your whims to fit the software’s design. Since customizing Devise’s sign_up method is so tedious, why don’t we work within the Rails defaults to create a simpler, more beautiful solution?

Here’s what I recommend: don’t add any custom fields to Devise’s registration form, and don’t run any custom code on sign_up. Redirect the user to OrganizationsController#new immediately after they signup, and disguise that page as the second step in your registration process:

“Thanks for joining! Now tell us a bit about your organization.”

Then, you can handle creating the organization inside OrganizationsController – where it should have been done all along. Because we’re playing with the Rails defaults, it’s easy to handle errors, write tests, and modify whatever we need to inside the associated controller. This approach requires less time and effort, and it produces a more stable result.