26
votes

In our application we have normal users. However, we want to be able to make invitations, to invite certain people. Note that an invitation is directly coupled to a user, as we want to be able to set certain settings for these users already. (We are mitigating clients from our old software to the new).

So:

  • An admin should be able to create a new user and change its settings.
  • When someone follows a link with their invitation_token, they should see a form where they can set a password for their account.

What I am having trouble with, is how to enable the admin to create an user account, bypassing the normal password validation. It would be a horrible solution if a default password would need to be set, as this would create a severe security flaw.

How to create a new User in Devise without providing a password?

3
Are you seeing a database constraint error or is your new user record just not valid? ?Josh

3 Answers

69
votes

There are at least two ways to do what you want:

Method 1:

Overload Devise's password_required? method

class User < ActiveRecord::Base
  attr_accessor :skip_password_validation  # virtual attribute to skip password validation while saving

  protected

  def password_required?
    return false if skip_password_validation
    super
  end
end

Usage:

@user.skip_password_validation = true
@user.save

Method 2:

Disable validation with validate: false option:

user.save(validate: false)

This will skip validation of all fields (not only password). In this case you should make sure that all other fields are valid.

...

But I advise you to not create users without password in your particular case. I would create some additional table (for example, invitations) and store all required information including the fields that you want to be assigned to a user after confirmation.

6
votes

TL;DR:

user.define_singleton_method(:password_required?) { false }

Fiddle:

class MockDeviseUser
  protected
  def password_required?
    true
  end
end

class User < MockDeviseUser
  def is_password_required?
    puts password_required?
  end
end

unrequired_password_user = User.new
unrequired_password_user.define_singleton_method(:password_required?) { false }
unrequired_password_user.is_password_required?
regular_user = User.new
regular_user.is_password_required?
#false
#true
1
votes

You can now use the DeviseInvitable gem for this.

It allows you to do exactly what you're asking.