Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails record mysteriously frozen, silently discarding updates

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
like image 479
Leo Avatar asked Jan 14 '19 19:01

Leo


1 Answers

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
like image 90
tpett Avatar answered Nov 11 '22 14:11

tpett