我有一个带有users
表的Rails应用程序。 PostgreSQL是数据库。由于某种原因,对一个用户记录的所有更新都会成功,然后以静默方式还原。发生了什么事?
损坏:
> 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???
相同的操作适用于其他用户:
> 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
我正在使用paper_trail gem进行版本控制,但是找不到冻结该gem中对象的任何功能。
paper_trail
配置为忽略last_access
列:
has_paper_trail ignore: %i[created_at last_access last_login updated_at]
该列上有一个PostgreSQL索引:
t.index ["last_access", "last_login"], name: "index_users_on_last_access_and_last_login", using: :btree
损坏的用户记录未在ActiveRecord中冻结:
> User.find_by(username: 'alice').frozen?
=> false
答案 0 :(得分:6)
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