Skip to content

Instantly share code, notes, and snippets.

@cmattson
Last active August 2, 2021 21:15
Show Gist options
  • Save cmattson/5851567 to your computer and use it in GitHub Desktop.
Save cmattson/5851567 to your computer and use it in GitHub Desktop.
Stupid Devise Tricks

Stupid Devise Tricks

Devise can be a daunting beast even if you've used it frequently. For new users, it can be especially baffling as the documentation often assumes a familiarity with its inner workings. To help bridge the gap, here are some frequent scenarios and possible solutions.

###Oh my God, it's complaining about unknown methods! What?!

This most commonly occurs because you have enabled features in your Devise model (e.g. user.rb) but didn't create the associated fields with a migration.

Devise's tendrils are manifold; each feature has an associated symbol in your model's devise block, field(s) in your database, and configuration options in your Devise initializer.

If you haven't already moved twelve migrations ahead of generating your Devise model, this is very easily resolved by uncommenting the appropriate sections of your Devise migration. Also remember to uncomment the associated indexes. A quick rake db:migrate:redo (possibly the most underappreciated migration option) and you're set.

If you've already moved several migrations ahead of generating your Devise model, copy and paste the missing fields from the initial Devise migration into a new migration.


I turned on confirmation and now nobody can log in!

As mentioned above, the Devise experience involves the model, the database, and the initializer. Any time you touch one, you should be touching the others.

Open your config/initializers/devise.rb and scan through for #==> Configuration for :confirmable. Adjust your configuration options as desired.

In Development

If you've set your configuration options, confirmable's almost certainly working as intended... but you're probably not getting your confirmation emails.

Several options here:

  1. Make sure Rails is configured to use a live SMTP server. (If you're using emails as your key, or otherwise enforcing email uniqueness, this does mean you'll need a steady supply of unique emails.)
  2. Confirmation emails for new users show up in the log as they're generated. Grab the link there.
  3. Fire up the console and manually mark accounts confirmed with the confirmed! method.
  4. Go get a beer and let someone else deal with it.

In Production

Why did you push a change without thorough testing? Shame, Shame, DJ!

The easiest way to solve this is to mark your existing users as confirmed. It's easier than you think: Devise just looks for the confirmed_at column to be populated, and now even provides a convenience method (confirm!) on the model to do it.

If you want to make your existing users confirm their emails, that's left as an exercise for the reader. (The droids you're looking for are in the example block.)


Confirmation has a grace period, but new users still aren't signed in automatically.

It's a feature! A frequently-maligned, non-configurable feature!

There are two things to know here:

  1. Devise controllers, like the RegistrationsController, are easily overridden.
  2. Though it's referenced only obliquely in only some of the docs, an "inactive" account is an unconfirmed account. Any time you're scratching your head and it involves an unconfirmed account, scan the docs for inactive.

Devise's partials throw errors

The Devise partials are for use by Devise in Devise views only. The variables will not be populated when rendered or duplicated outside of the Devise views.

The "resource" resource_name is referencing is your model. For example, if you're using a User model, passing :user works quite nicely:

<% unless user_signed_in? %>
  <%= link_to "Sign up", new_registration_path(:user) %>
<% end %>

Rememberable's turned on, but it's not remembering.

This is almost always caused by also enabling Timeoutable.

Rememberable will keep the user logged in only until they're explicitly logged out—whether they do that by themselves or it's done programatically (e.g., by Timeoutable).

In most cases the two options are mutually exclusive, but they can be used together in weird situations with strange business requirements. Adjust the timeouts for both to similar values and update any "Remember me for [TIME]" verbiage in your views.


So I followed the Devise HOWTO to set up OAuth...

You don't need the name column. Though it's in the tutorial, it serves no actual purpose for Devise or OmniAuth.

The required fields are uid and provider.

If your user model already defines, say, first_name and last_name, go on using those.


I need to send params with an OAuth request and get them back.

See https://gist.github.com/cmattson/5847954


I trust the OAuth provider. Can I skip confirming OAuth users?

Yes. Devise models provide a skip_confirmation! method that will mark a record as confirmed and skip sending the confirmation email.

N.B.: This must be called before the record is saved. The confirmation mailer fires immediately upon save. If you're currently creating your users with create (as in the tutorial), you'll need to convert to new with an explicit save:

user = User.new(
  # Your code here
)
user.skip_confirmation!
user.save

Rails 4 complains about duplicate routes

You'll only run into this one if you're making use of Devise's ability to map routes inside of an authenticated block.

Several versions of Devise ago, you gained the ability to do something like this:

root :to => 'welcome#index'

authenticated :user do
  root :to => 'member#index'
end

Due to routing changes in Rails 4, this is no longer allowed. The first time you try to spin up your app or check the route layout, Rails will vomit. This is easily fixed by assigning a different name to the authenticated root:

authenticated :user do
  root :to => 'member#index', :as => :authenticated_root
end

For more details, see Devise issue #2393.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment