Nathan Hanna
Nathan Hanna

Reputation: 4963

How can I save a reset_password_token at the time I create a new Devise user?

When I try to create a new Devise user, I get the error:

ActiveRecord::RecordNotUnique: TinyTds::Error: Cannot insert duplicate key row in object 'dbo.admin_users' with unique index 'index_admin_users_on_reset_password_token'. The duplicate key value is (NULL)

This is because the index 'index_admin_users_on_reset_password_token' requires unique values in the reset_password_token field, and every User that gets created is submitted with a nil value in that field, which means every record past the first will not be unique.

When I try to manually submit a value in that field it is automatically ommitted.

user = AdminUser.new(email: "[email protected]", password: "integracore", reset_password_token:"french fries", reset_password_sent_at: Time.now)
#<AdminUser:0x000000075303e8
# id: nil,
# email: "[email protected]",
# encrypted_password: "$2a$10$cm9AmPuwEey4hDFMUPMMkeD3bLPozT47VLdmg9kDlDRKBXh93Hn0C",
# reset_password_token: "french fries",
# reset_password_sent_at: Thu, 03 Sep 2015 19:42:25 UTC +00:00,
# remember_created_at: nil,
# sign_in_count: 0,
# current_sign_in_at: nil,
# last_sign_in_at: nil,
# current_sign_in_ip: nil,
# last_sign_in_ip: nil,
# created_at: nil,
# updated_at: nil>
user.save

ActiveRecord::RecordNotUnique: TinyTds::Error: Cannot insert duplicate key row in object 'dbo.admin_users' with unique index 'index_admin_users_on_reset_password_token'. The duplicate key value is ().: EXEC sp_executesql N'INSERT INTO [admin_users] ([email], [encrypted_password], [created_at], [updated_at]) OUTPUT INSERTED.[id] VALUES (@0, @1, @2, @3)', N'@0 nvarchar(4000), @1 nvarchar(4000), @2 datetime, @3 datetime', @0 = N'[email protected]', @1 = N'$2a$10$cm9AmPuwEey4hDFMUPMMkeD3bLPozT47VLdmg9kDlDRKBXh93Hn0C', @2 = '09-03-2015 19:45:11.555', @3 = '09-03-2015 19:45:11.555'

How can I get past this error and create a new user?

Upvotes: 0

Views: 333

Answers (1)

Nathan Hanna
Nathan Hanna

Reputation: 4963

So I added this workaround for the time being. I basically just update all NULL records before and after creating a new user. I would prefer to do it the 'Devise way' so if someone posts that I will choose that as the answer, but this will work for now:

class AdminUser < ActiveRecord::Base
  devise :database_authenticatable, 
         :recoverable, :rememberable, :trackable, :validatable

  # Create new user #############################################################
    def self.add_user (email:,password:"password")
      clean_empty_reset_tokens
      user = self.create(email:email,password:password)
      user.set_reset_token
      return user
    end

    def set_reset_token token = self.class.generate_token
      update(reset_password_token: token)
      return token
    end

    def self.clean_empty_reset_tokens
      where(reset_password_token:nil).each do |user|
        user.update(reset_password_token:generate_token)
      end
    end

    def self.generate_token
        raw_token, hashed_token = Devise.token_generator.generate(self, :reset_password_token)
        return hashed_token
    end
  # End create new user #########################################################
end

Upvotes: 0

Related Questions