I have a Rails app with a users
table. PostgreSQL is the database. For some reason, all updates to one of the user records succeed and then silently revert. What is going on?
Broken:
> u = User.find_by(username: 'alice')
> u.last_access
=> Thu, 19 Jul 2018 17:59:35 UTC +00:00
> u.last_access -= 20.days
=> Fri, 29 Jun 2018 17:59:35 UTC +00:00
> u.save!
(1.6ms) BEGIN
...
User Update (1.4ms) UPDATE "users" SET "updated_at" = $1, "last_access" = $2 WHERE "users"."id" = $3 [["updated_at", "2019-01-14 19:02:56.271382"], ["last_access", "2018-06-29 17:59:35"], ["id", 1]]
(0.8ms) COMMIT
=> true
> reload!
> User.find_by(username: 'alice').last_access
=> Thu, 19 Jul 2018 17:59:35 UTC +00:00
> # WHY NOT 29 JUN???
The same operations work for a different user:
> u = User.find_by(username: 'bob')
> u.last_access
=> Mon, 24 Dec 2018 03:33:47 UTC +00:00
> u.last_access -= 20.days
=> Tue, 04 Dec 2018 03:33:47 UTC +00:00
> u.save!
(1.8ms) BEGIN
...
User Update (6.3ms) UPDATE "users" SET "updated_at" = $1, "last_access" = $2 WHERE "users"."id" = $3 [["updated_at", "2019-01-14 18:59:56.087223"], ["last_access", "2018-12-04 03:33:47"], ["id", 2]]
(2.0ms) COMMIT
=> true
> reload!
> User.find_by(username: 'bob').last_access
=> Tue, 04 Dec 2018 03:33:47 UTC +00:00
> # GOOD
I'm using the paper_trail gem for versioning, but I can't find any feature for freezing objects in that gem.
paper_trail
is configured to ignore the last_access
column:
has_paper_trail ignore: %i[created_at last_access last_login updated_at]
There is a PostgreSQL index on the column:
t.index ["last_access", "last_login"], name: "index_users_on_last_access_and_last_login", using: :btree
The broken user record isn't frozen in ActiveRecord:
> User.find_by(username: 'alice').frozen?
=> false
If you execute the update on the database directly does the change take affect? For instance, you could do:
User.connection.execute 'UPDATE "users" SET "last_access" = \'2018-12-04 03:33:47\' WHERE username = 'alice'
If the change doesn't take affect at that point then I would suspect that there is a trigger or something in your database that is causing the strange behavior.
Edit:
It's very strange to me that your log shows a successful update from Rails but the record isn't actually being changed. I'm still not convinced that there isn't something going on in the database.
Try doing a schema dump of that table and carefully look through it for any triggers that might be causing the value to be changed out from under you.
pg_dump -t 'public.users' --schema-only DB_NAME
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With