Joelio
Joelio

Reputation: 4691

devise save user causes reset_password_token to be set to nil

This just started happening, I am not sure when or what caused it, but for some reason devise is clearing my reset_password_token on save.

In order to debug my problem, I implemented

  def reset_password_token=(token)
    debugger
    self[:reset_password_token] = token
  end

on my User object so I could see who was setting it.

Whenever I do user.save(), my reset_password_token gets set to nil, here is the callstack:

--> #0  User.reset_password_token=(token#NilClass) at /Users/joelnylund/Projects/myproject/adv/app/models/user.rb:125
    #1  Devise::Models::Recoverable.clear_reset_password_token at /Users/joelnylund/.rvm/gems/ruby-2.0.0-p353/gems/devise-3.5.1/lib/devise/models/recoverable.rb:97
    #2  block (2 levels) in <module:Recoverable> at /Users/joelnylund/.rvm/gems/ruby-2.0.0-p353/gems/devise-3.5.1/lib/devise/models/recoverable.rb:36
    ͱ-- #3  BasicObject.instance_exec(*args) at /Users/joelnylund/.rvm/gems/ruby-2.0.0-p353/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:446
    #4  block in ActiveSupport::Callbacks::Callback.make_lambda(filter#Proc) at /Users/joelnylund/.rvm/gems/ruby-2.0.0-p353/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:446
    ͱ-- #5  Proc.call(*args) at /Users/joelnylund/.rvm/gems/ruby-2.0.0-p353/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:164
    #6  block in #<Class:ActiveSupport::Callbacks::Filters::Before>.halting(callback_sequence#ActiveSupport::Callbacks::CallbackSequence, user_callback#Proc, halted_lambda#Proc, filter#Proc) at /Users/joelnylund/.rvm/gems/ruby-2.0.0-p353/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:164
    ͱ-- #7  Proc.call(*args) at /Users/joelnylund/.rvm/gems/ruby-2.0.0-p353/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:504
    #8  block in ActiveSupport::Callbacks::CallbackSequence.call(*args#Array) at /Users/joelnylund/.rvm/gems/ruby-2.0.0-p353/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:504
    ͱ-- #9  Array.each at /Users/joelnylund/.rvm/gems/ruby-2.0.0-p353/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:504
    #10 ActiveSupport::Callbacks::CallbackSequence.call(*args#Array) at /Users/joelnylund/.rvm/gems/ruby-2.0.0-p353/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:504
    #11 ActiveSupport::Callbacks._run_callbacks(callbacks#ActiveSupport::Callbacks::CallbackChain, &block#Proc) at /Users/joelnylund/.rvm/gems/ruby-2.0.0-p353/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:92
    #12 ActiveRecord::Base._run_save_callbacks(&block#Proc) at /Users/joelnylund/.rvm/gems/ruby-2.0.0-p353/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:776
    #13 ActiveRecord::Callbacks.create_or_update at /Users/joelnylund/.rvm/gems/ruby-2.0.0-p353/gems/activerecord-4.2.1/lib/active_record/callbacks.rb:302
    #14 ActiveRecord::Persistence.save(*args) at /Users/joelnylund/.rvm/gems/ruby-2.0.0-p353/gems/activerecord-4.2.1/lib/active_record/persistence.rb:120
    #15 ActiveRecord::Validations.save(*args) at /Users/joelnylund/.rvm/gems/ruby-2.0.0-p353/gems/activerecord-4.2.1/lib/active_record/validations.rb:37
    #16 ActiveRecord::AttributeMethods::Dirty.save(*args) at /Users/joelnylund/.rvm/gems/ruby-2.0.0-p353/gems/activerecord-4.2.1/lib/active_record/attribute_methods/dirty.rb:21
    #17 block (2 levels) in ActiveRecord::Transactions.save(*args) at /Users/joelnylund/.rvm/gems/ruby-2.0.0-p353/gems/activerecord-4.2.1/lib/active_record/transactions.rb:286
    #18 block in ActiveRecord::Transactions.with_transaction_returning_status at /Users/joelnylund/.rvm/gems/ruby-2.0.0-p353/gems/activerecord-4.2.1/lib/active_record/transactions.rb:347
    #19 block in ActiveRecord::ConnectionAdapters::DatabaseStatements.transaction(options#Hash) at /Users/joelnylund/.rvm/gems/ruby-2.0.0-p353/gems/activerecord-4.2.1/lib/active_record/connection_adapters/abstract/database_statements.rb:213
    #20 ActiveRecord::ConnectionAdapters::TransactionManager.within_new_transaction(options#Hash) at /Users/joelnylund/.rvm/gems/ruby-2.0.0-p353/gems/activerecord-4.2.1/lib/active_record/connection_adapters/abstract/transaction.rb:188
    #21 ActiveRecord::ConnectionAdapters::DatabaseStatements.transaction(options#Hash) at /Users/joelnylund/.rvm/gems/ruby-2.0.0-p353/gems/activerecord-4.2.1/lib/active_record/connection_adapters/abstract/database_statements.rb:213
    #22 ActiveRecord::Transactions::ClassMethods.transaction(options#Hash, &block#Proc) at /Users/joelnylund/.rvm/gems/ruby-2.0.0-p353/gems/activerecord-4.2.1/lib/active_record/transactions.rb:220
    #23 ActiveRecord::Transactions.with_transaction_returning_status at /Users/joelnylund/.rvm/gems/ruby-2.0.0-p353/gems/activerecord-4.2.1/lib/active_record/transactions.rb:344
    #24 block in ActiveRecord::Transactions.save(*args) at /Users/joelnylund/.rvm/gems/ruby-2.0.0-p353/gems/activerecord-4.2.1/lib/active_record/transactions.rb:286
    #25 ActiveRecord::Transactions.rollback_active_record_state! at /Users/joelnylund/.rvm/gems/ruby-2.0.0-p353/gems/activerecord-4.2.1/lib/active_record/transactions.rb:301
    #26 ActiveRecord::Transactions.save(*args) at /Users/joelnylund/.rvm/gems/ruby-2.0.0-p353/gems/activerecord-4.2.1/lib/active_record/transactions.rb:285
    #27 Admin::UsersController.create at /Users/joelnylund/Projects/myproject/adv/app/controllers/admin/users_controller.rb:88

In devise I see this:

 if email_changed? || encrypted_password_changed?
        clear_reset_password_token
 end

If this is true, how am I supposed to set the token and create the user at the same time. The work around I found is after the save to set just the token and that seems to have worked, but not sure why this just started happening..

Upvotes: 2

Views: 254

Answers (2)

mattwd7
mattwd7

Reputation: 57

Just dealt with this and came here for advice. After some fiddling and testing, my solution was simply to perform a save on the object to clear the _changed? log. I do this in after_create for the User:

def email_credentials
    self.save
    self.send_reset_password_instructions
end

Upvotes: 1

Tyler Liu
Tyler Liu

Reputation: 20356

I meet the same issue. It seems that the only solution is to save the user before set reset_password_token

user = User.new
user.email = '[email protected]'
user.save # save
user.reset_password_token = 'token'
user.reset_password_sent_at = Time.now.utc
user.save # save again

Upvotes: 1

Related Questions