2

I've come across a strange situation updating a rails 4.2 app to 5.1. For debugging purposes I have removed everything from the user model, it is now completely empty standard model:

class User < ActiveRecord::Base
end

I'm having problems with tests on this model and I've tracked it down to the behavior of will_save_change_to_password. The problem I am seeing is:

[1] pry> user = User.new(...)
  => #<User:0x007fa5abbe02f0 ... >
[2] pry> user.save
  => true
[3] pry> user.will_save_change_to_password?
  => nil
[2] pry> user
  => #<User:0x007fa5abbe02f0 ... >
[4] pry> user.will_save_change_to_password?
  => true
[5] pry> user.changes
  => {"username"=>["68c0bad3-d661-4008-9728-2dcb192f2ba1", "68c0bad3-d661-4008-9728-2dcb192f2ba1"], "password"=>["cebb41d5-5421-4de6-8c48-04ce735b1bb7", "cebb41d5-5421-4de6-8c48-04ce735b1bb7"]}

This is making absolutely no sense to me. After saving the model AR agrees there will be no change to the password. Then you access the user object (you can also call a method on the user object with the same effect) and suddenly it thinks the password will change. And if you ask it, it says the password is changing to the exact same password (same for username)!

I would LOVE any insight into wtf is going on here, I've been banging my head on the wall for a while on this one trying to understand it.

Chad
  • 768
  • 1
  • 6
  • 20
  • Can you include the code for `will_save_change_to_password?`. On a side note, entering an object into console, will do `object.inspect` which normally defaults to `object.to_s`, but for an `ActiveRecord::Base` object in particular, I traced the method call just now by running `trace do user.inspect end`, of which amongst the trace-lines I got [this](http://api.rubyonrails.org/classes/ActiveRecord/Core.html#method-i-inspect)... – Jay-Ar Polidario Jun 14 '18 at 21:22
  • ...of which it's calling `attribute_for_inspect`, and then leading me to search`def attribute_for_inspect` in [rails github search](https://github.com/rails/rails/blob/d0d3e964920602aa710507f6717010d852e37c86/activerecord/lib/active_record/attribute_methods.rb#L346). I found out it's doing a `read_attribute`... <-- and this might be doing some things that affected the result of your `will_save_change_to_password?` – Jay-Ar Polidario Jun 14 '18 at 21:24
  • We can rule out the case above of which I just wrote (that `read_attribute` is doing some things unintended for your case), by... instead of `[2] pry> user`, type in `[2] pry> user;nil` instead. And then run `pry> user.will_save_change_to_password?` afterwards again. If this still returns `true`, then the problem does not have anything to do with `object.inspect` and thus not have anything to do with what I just said in previous comments, and that the problem is most likely something else (that I do not know yet of). Showing however `will_save_change_to_password?` code might help me a little – Jay-Ar Polidario Jun 14 '18 at 21:30
  • BTW, (forgot to mention; couldn't edit the comment now), but for `trace do user.inspect end` in my first comment above, if you're interested, I used this [trace gem](https://github.com/codegram/trace) to debug – Jay-Ar Polidario Jun 14 '18 at 21:32
  • will_save_change_for_password? is part of activerecord, there is no code in my app for it. http://api.rubyonrails.org/classes/ActiveRecord/AttributeMethods/Dirty.html#method-i-will_save_change_to_attribute-3F – Chad Jun 14 '18 at 21:54
  • Oh you're right! Good to know :) Just for reference, I didn't encounter your problem after replicating your scenario (using ruby 2.5.1). My steps (for documentation): `gem install rails --version=5.1`, `rails _5.1_ new some_app`, `cd some_app`, `rails g model user email password`, `rake db:migrate`, `bundle add pry-rails --group=development`, `rails c`, `user = User.new`, `user.save`, `user.will_save_change_to_password?`, `user`, `user.will_save_change_to_password?` – Jay-Ar Polidario Jun 14 '18 at 22:09
  • ...so at the moment, I do not yet have any clue what the problem is. Other possible debugging steps would be: manually try (temporarily) removing each gem from your `Gemfile` one by one (cross-checking each time if your problem still exists), or... try doing `user;nil` instead of `user` in pry (I said above), or try switching ruby versions (i.e. exactly the one I have already tested: 2.5.1). If problem still persists, try doing a `trace` on the method calls for `user` (when you type `user` into pry), and look for "suspiciously" called methods in the trace-lines. i.e. I use `trace` gem – Jay-Ar Polidario Jun 14 '18 at 22:14
  • you can also use `byebug` to incrementally "step" (or "pause") and debug into the method calls so that you can inspect what's being called after you type `user` into pry – Jay-Ar Polidario Jun 14 '18 at 22:16
  • one more thing, try entering `spring stop` in your command line, or open a new terminal and run pry there, this usually fixes some of the "weird" things. – Jay-Ar Polidario Jun 14 '18 at 22:19
  • also, lastly, try updating your rails version, maybe there was actually a bug somewhere in `rails 5.1.X`, and that maybe at `5.1.6` (the one I tested which is currently the latest 5.1.X version), it's already been fixed. – Jay-Ar Polidario Jun 14 '18 at 22:23
  • I am curious if you forgot to start a new console after saving the changes where you stripped down your model. I have experienced this exact behavior with fields that use the cryptkeeper gem. If you're using a gem to encrypt the field, it's likely touching that field every time the record is saved. – Allison Nov 08 '19 at 04:04

0 Answers0