Hi,
I have problems with:
NoMethodError (undefined method `will_save_change_to_email?' for #<User:0x007f80b1778ec0>):
activesupport (5.1.1) lib/active_support/callbacks.rb:413:in `block in make_lambda'
activesupport (5.1.1) lib/active_support/callbacks.rb:177:in `block (2 levels) in halting_and_conditional'
activesupport (5.1.1) lib/active_support/callbacks.rb:177:in `each'
activesupport (5.1.1) lib/active_support/callbacks.rb:177:in `all?'
activesupport (5.1.1) lib/active_support/callbacks.rb:177:in `block in halting_and_conditional'
activesupport (5.1.1) lib/active_support/callbacks.rb:507:in `block in invoke_before'
activesupport (5.1.1) lib/active_support/callbacks.rb:507:in `each'
activesupport (5.1.1) lib/active_support/callbacks.rb:507:in `invoke_before'
activesupport (5.1.1) lib/active_support/callbacks.rb:130:in `run_callbacks'
mongoid (6.1.0) lib/mongoid/interceptable.rb:138:in `run_callbacks'
activesupport (5.1.1) lib/active_support/callbacks.rb:825:in `_run_validate_callbacks'
activemodel (5.1.1) lib/active_model/validations.rb:405:in `run_validations!'
activemodel (5.1.1) lib/active_model/validations/callbacks.rb:110:in `block in run_validations!'
activesupport (5.1.1) lib/active_support/callbacks.rb:131:in `run_callbacks'
mongoid (6.1.0) lib/mongoid/interceptable.rb:138:in `run_callbacks'
activesupport (5.1.1) lib/active_support/callbacks.rb:825:in `_run_validation_callbacks'
activemodel (5.1.1) lib/active_model/validations/callbacks.rb:110:in `run_validations!'
activemodel (5.1.1) lib/active_model/validations.rb:335:in `valid?'
mongoid (6.1.0) lib/mongoid/validatable.rb:97:in `valid?'
activemodel (5.1.1) lib/active_model/validations.rb:372:in `invalid?'
mongoid (6.1.0) lib/mongoid/persistable/creatable.rb:115:in `prepare_insert'
mongoid (6.1.0) lib/mongoid/persistable/creatable.rb:23:in `insert'
mongoid (6.1.0) lib/mongoid/persistable/savable.rb:23:in `save'
/Volumes/FdData/Users/mToribio/.rvm/gems/ruby-2.4.1/bundler/gems/devise_token_auth-73d82dbd0982/app/controllers/devise_token_auth/registrations_controller.rb:42:in `create'
actionpack (5.1.1) lib/action_controller/metal/basic_implicit_render.rb:4:in `send_action'
actionpack (5.1.1) lib/abstract_controller/base.rb:186:in `process_action'
actionpack (5.1.1) lib/action_controller/metal/rendering.rb:30:in `process_action'
actionpack (5.1.1) lib/abstract_controller/callbacks.rb:20:in `block in process_action'
activesupport (5.1.1) lib/active_support/callbacks.rb:131:in `run_callbacks'
actionpack (5.1.1) lib/abstract_controller/callbacks.rb:19:in `process_action'
actionpack (5.1.1) lib/action_controller/metal/rescue.rb:20:in `process_action'
actionpack (5.1.1) lib/action_controller/metal/instrumentation.rb:32:in `block in process_action'
activesupport (5.1.1) lib/active_support/notifications.rb:166:in `block in instrument'
activesupport (5.1.1) lib/active_support/notifications/instrumenter.rb:21:in `instrument'
activesupport (5.1.1) lib/active_support/notifications.rb:166:in `instrument'
actionpack (5.1.1) lib/action_controller/metal/instrumentation.rb:30:in `process_action'
actionpack (5.1.1) lib/action_controller/metal/params_wrapper.rb:252:in `process_action'
actionpack (5.1.1) lib/abstract_controller/base.rb:124:in `process'
actionview (5.1.1) lib/action_view/rendering.rb:30:in `process'
actionpack (5.1.1) lib/action_controller/metal.rb:189:in `dispatch'
actionpack (5.1.1) lib/action_controller/metal.rb:253:in `dispatch'
actionpack (5.1.1) lib/action_dispatch/routing/route_set.rb:49:in `dispatch'
actionpack (5.1.1) lib/action_dispatch/routing/route_set.rb:31:in `serve'
actionpack (5.1.1) lib/action_dispatch/routing/mapper.rb:16:in `block in <class:Constraints>'
actionpack (5.1.1) lib/action_dispatch/routing/mapper.rb:46:in `serve'
actionpack (5.1.1) lib/action_dispatch/journey/router.rb:46:in `block in serve'
actionpack (5.1.1) lib/action_dispatch/journey/router.rb:33:in `each'
actionpack (5.1.1) lib/action_dispatch/journey/router.rb:33:in `serve'
actionpack (5.1.1) lib/action_dispatch/routing/route_set.rb:832:in `call'
warden (1.2.7) lib/warden/manager.rb:36:in `block in call'
warden (1.2.7) lib/warden/manager.rb:35:in `catch'
warden (1.2.7) lib/warden/manager.rb:35:in `call'
rack (2.0.3) lib/rack/etag.rb:25:in `call'
rack (2.0.3) lib/rack/conditional_get.rb:38:in `call'
rack (2.0.3) lib/rack/head.rb:12:in `call'
actionpack (5.1.1) lib/action_dispatch/middleware/callbacks.rb:26:in `block in call'
activesupport (5.1.1) lib/active_support/callbacks.rb:97:in `run_callbacks'
actionpack (5.1.1) lib/action_dispatch/middleware/callbacks.rb:24:in `call'
actionpack (5.1.1) lib/action_dispatch/middleware/executor.rb:12:in `call'
actionpack (5.1.1) lib/action_dispatch/middleware/debug_exceptions.rb:59:in `call'
actionpack (5.1.1) lib/action_dispatch/middleware/show_exceptions.rb:31:in `call'
railties (5.1.1) lib/rails/rack/logger.rb:36:in `call_app'
railties (5.1.1) lib/rails/rack/logger.rb:24:in `block in call'
activesupport (5.1.1) lib/active_support/tagged_logging.rb:69:in `block in tagged'
activesupport (5.1.1) lib/active_support/tagged_logging.rb:26:in `tagged'
activesupport (5.1.1) lib/active_support/tagged_logging.rb:69:in `tagged'
railties (5.1.1) lib/rails/rack/logger.rb:24:in `call'
actionpack (5.1.1) lib/action_dispatch/middleware/remote_ip.rb:79:in `call'
actionpack (5.1.1) lib/action_dispatch/middleware/request_id.rb:25:in `call'
rack (2.0.3) lib/rack/runtime.rb:22:in `call'
activesupport (5.1.1) lib/active_support/cache/strategy/local_cache_middleware.rb:27:in `call'
actionpack (5.1.1) lib/action_dispatch/middleware/executor.rb:12:in `call'
actionpack (5.1.1) lib/action_dispatch/middleware/static.rb:125:in `call'
rack (2.0.3) lib/rack/sendfile.rb:111:in `call'
rack-cors (0.4.1) lib/rack/cors.rb:81:in `call'
railties (5.1.1) lib/rails/engine.rb:522:in `call'
puma (3.8.2) lib/puma/configuration.rb:224:in `call'
puma (3.8.2) lib/puma/server.rb:600:in `handle_request'
puma (3.8.2) lib/puma/server.rb:435:in `process_client'
puma (3.8.2) lib/puma/server.rb:299:in `block in run'
puma (3.8.2) lib/puma/thread_pool.rb:120:in `block in spawn_thread'
In rails 5.0 thats works good.
I have been investigating a little more and I not found where is defined will_save_change_to_email?.
I think thats could be the problem...
For now, I will use Rails 5.0 but I would like use Rails 5.1.
Thanks in advance.
I have the same problem. I'm using mongoid 6.1 and Active Record. According to the comment in 3e1c9e3 it's not working at the moment. Also related to this issue.
I am not sure what exactly transpired to have caused this error. It seems that all of a sudden I'm getting the same Undefined method will_save_change_to_email? for User error.
So, a quick monkey patch, at least for the time being, is to just define will_save_change_to_email? in the model, in my particlar case, the model was User, so I defined it in there as follows:
def will_save_change_to_email?
end
This resolves the problem, at least in my case it did.
The issue here is that method
def will_save_change_to_email?
end
is not even defined in the devise gem.
Although it is referenced in the callback, in the following files:
lib/devise/models/confirmable.rb
lib/devise/models/validatable.rband
test/rails_app/lib/shared_admin.rb
it is not defined whatsoever.
Please note that this problem is only raised and replicated when using Mongoid as of today's date, 7/9/2017.
The problem does not exist when using Active Record.
I've facing this issue with ActiveRecord.
rails (5.1.2)
devise (4.3.0)
Do you have the mongoid gem installed? You probably do, as one could still have both, Active Record and Mongoid in the same app. I don't think the issue is stemming from Active Record, if that was the case, then a significant amount of Rails apps would break, and it would have been resolved a long time ago, not exactly sure what the source of the issue is other than what I described above. At any rate, did you define the method will_save_change_to_email? in your model? For me, all I did is simply define it in my model like this:
def will_save_change_to_email?
end
And it worked like a charm.
I'm using:
Rails (5.1.2)
Devise (4.3.0)
Mongoid (6.2.0)
ActiveRecord (5.1.2)
Naturally, when using Mongoid for example, it seems that Devise is calling a "will_save_change_to_email?" method without defining it, it's probably depending on mongoid supplying that method, I think. So, whatever the reason, I simply defined the missing method, and it ended up working great for me.
If you ended up resolving the problem another way, please share your solution with the community on here, perhaps there's a better way than monkey-patching stuff :)
So it turns out that the model does not have an email attribute, and both email_required? and email_changed? had been defined inside the model to negate the validation in previous versions.
The project is one I've inherited and had the pleasure of taking from Rails 3 all the way up to 5.1, while switching from MySQL to Postgresql. It's been, interesting...
TL;DR:
def will_save_change_to_email?
false
end
works fine for me!
Hello @mtoribio, thanks for your report.
Can you provide us a sample application that reproduces the issue in isolation?
That would help us find the issue.
Thank you!
I got a same error.
My environment is below.
ruby 2.4.3p205 (2017-12-14 revision 61247) [x86_64-darwin16]
rails (5.1.4)
devise (4.3.0)
I dont use mongoid, Im using mysql.
And the table we use for devise doesnt have column the name of 'email'.
I think you can reproduce this error by creating app using devise without using email column.
Sorry I dont have time to create public repo, but I wish this will help you.
@nao215 what devise modules are you using in your model? validatable requires an email attribute and we also call this method on confirmable (but I guess you don't use confirmable since you don't have an email column)
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:confirmable,
authentication_keys: [:agency_email]
config.case_insensitive_keys = [ :agency_email ]
config.strip_whitespace_keys = [ :agency_email ]
config.confirmation_keys = [ :agency_email ]
config.reset_password_keys = [ :agency_email ]
this is our code for devise.
Sorry, I have a lot of client and it was just quick look.
The error happened when we try to up rails version to 5.
I guess
https://github.com/plataformatec/devise/commit/3e1c9e343ce537e3c9aabd74592e375152482045
This is the reason maybe.
We used validatable from rails 4 and we version uped.
Thanks to Devise.activerecord51?, we can use validatable without 'email' but version up to rails 5, Devise.activerecord51? return true and we cannot use validatable without email column.
Thanks for you reply and sorry for dirty english.
I think the best way is use column which name is "email".
@nao215 But even when you hit the else clause, the method email_changed? will be called. If you don't have that column I guess this method doesn't exist on your model too, right?
@tegon
But even when you hit the else clause, the method email_changed? will be called.
Yes, but the error is undefined method 'will_save_change_to_email?', not undefined method 'email_changed?'.
I cant find definition of will_save_change_to_email but this is looks like auto generated method so I guess if we dont use column name of email, not generated. ※ just I guess
@nao215 What I meant is that is weird this worked before you update rails, because even though Devise.activerecord51? returns false, the method will_save_change_to_email? won't be called, but email_changed? would. Does your model responds to email_changed??
I've run into this as well.
The problem appears to be that devise only makes a global check for Devise.activerecord51? without consulting which ORM is actually storing the User model. In our case the User model is backed by Mongoid 6.4.1, not ActiveRecord. So devise is trying to call AR methods on a mongoid model which doesn't support them.
@mbell697 Can you provide us a sample application that reproduces the issue in isolation?
Another option is to use our bug report template.
That would help us find the issue.
@tegon If you modify your test suite to load both Mongoid and ActiveRecord, but test Mongoid backed device models, you'll likely see a bunch of failures. Can probably just make a quick change here (https://github.com/plataformatec/devise/blob/master/test/rails_app/config/application.rb#L12) to always load active record and run the suite with DEVISE_ORM=mongoid.
I ran into this as well, from a clean new rails application.
STR:
1.) rails new auth_test
2.) add and configure mongoid
3.) add and configure devise
4.) generate new User model using devise generator (generates a mongoid model)
5.) can't sign up (undefined method 'will_save_change_to_email?' for User)
You can fix this problem by not including ActiveRecord: rails new auth_test -O
Related sample application
https://github.com/plataformatec/devise/pull/4910#issuecomment-413359139
If you are using Rails 5.x with MongoID and NOT active record then you must comment out "require 'active_storage/engine'" in the application.rb.
Active storage uses Active record.
Example
require_relative 'boot'
require 'rails'
# Pick the frameworks you want:
require 'active_model/railtie'
require 'active_job/railtie'
# require 'active_storage/engine'
require 'action_controller/railtie'
require 'action_mailer/railtie'
require 'action_view/railtie'
require 'action_cable/engine'
require 'sprockets/railtie'
# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)
module ReadSharedBooks
class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 5.2
# Settings in config/environments/* take precedence over those specified here.
# Application configuration can go into files in config/initializers
# -- all .rb files in that directory are automatically loaded after loading
# the framework and any gems in your application.
# Don't generate system test files.
config.generators.system_tests = nil
end
end
@mtoribio @aalbagarcia @codewizardry @chrise86 @tegon please have a look on this
I am still face problem with this.. I am using
I need both mongoid and activerecord on my system.. the User class uses mongoid and has a field called email. Everything was working perfectly on rails 5.0 but since I updated Rails to 5.1.7 I get this message undefined method will_save_change_to_email?. I tried doing what it was suggested here on this thread, creating a method called will_save_change_to_email? on User.rb. but the expected behaviour is still not right. For example, when the user changes his email, Devise is not sending the email for the user to confirm his email again. Instead I just see a notice message saying that my data was updated, which means that I see the registrations.updated message instead of registrations.update_needs_confirmation message.
Any updates on this?
@chrisokamoto Unfortunately, I haven't been able to dig deep into this yet. I'll try to do it soon.
setting this 3 aliases "solved" the problem for me for now:
alias will_save_change_to_email? email_changed?
alias email_in_database email_was
alias email_before_last_save email_before_destroy_was
I define email as a virtual attribute and I found out that I need to call define_attribute_method with it.
Default prefixes and suffixes are defined in ActiveRecord::AttributeMethods::Dirty. ActiveModel::AttributeMethods is also already included by ActiveRecord::AttributeMethods, which is also included by ActiveRecord::Base. Rails version 6.0.0.
Edit: I actually might need to do something more than that because the generic methods declared in ActiveRecord::AttributeMethods::Dirty may not apply to a virtual attribute. I might as well just create custom methods unless I find a generic solution.
create a function in model file
def will_save_change_to_email?
false
end
For info...
I just upgrade an app from Rails 5.2.4.3 (which does not exhibit this issue) to 5.2.4.5 and this error appeared. I am using Mongoid for database and thought I inhibited the ActiveRecord per the Mongoid instructions.
In Rails 5.2.4.3:
defined?(ActiveRecord)
> nil
In Rails 5.2.4.5
defined?(ActiveRecord)
> "constant"
This appears to be causing Devise.activerecord51? to be true and the root cause of the undefined method will_save_change_to_email? error.
From the Mongoid docs...
Sometimes Spring tries to load ActiveRecord even when the application contains no ActiveRecord references. If this happens, add an ActiveRecord adapter dependency such as sqlite3 to your Gemfile so that ActiveRecord may be completely loaded or remove Spring from your application.
After removing spring from Gemfile, this issue still occurs:
Under Rails 5.2.4.3, defined?(ActiveRecord) returns nil
Under Rails 5.2.4.5, defined?(ActiveRecord) returns true
UPDATE: DatabaseCleaner gem was including ActiveRecord. Use database_cleaner-mongoid instead.
Most helpful comment
So it turns out that the model does not have an email attribute, and both
email_required?andemail_changed?had been defined inside the model to negate the validation in previous versions.The project is one I've inherited and had the pleasure of taking from Rails 3 all the way up to 5.1, while switching from MySQL to Postgresql. It's been, interesting...
TL;DR:
works fine for me!