Rails 4:.save 不会更新现有记录的 updated_at? [英] Rails 4: .save does not update updated_at for existing records?
问题描述
我一直认为 .save
和 .save!
会更新现有记录的 updated_at
列.这不是真的吗?如果是这样,那么我是否需要创建一个 before_save 过滤器来在每次保存时更新它?
今天是 6 月 18 日:
加载开发环境(Rails 4.1.1)irb(main):001:0>o = 订单.last订单加载 (0.4ms) SELECT `orders`.* FROM `orders` ORDER BY `orders`.`id` DESC LIMIT 1=>#<订单id:24,user_id:1,order_date:nil,total_cents:0,total_currency:USD",shipping_cents:0,shipping_currency:USD",tax_cents:0,tax_currency:USD",subtotal_cents:0,subtotal_currency: "USD", created_at: "2014-06-13 21:24:38", updated_at: "2014-06-13 21:24:38", status: "Incomplete",coupon_id: nil>irb(main):002:0>o.保存!(0.4ms) 开始(0.3ms) 提交=>真的irb(main):003:0>o.updated_at=>2014 年 6 月 13 日星期五 21:24:38 UTC +00:00irb(main):004:0>o.重新加载订单加载 (0.7ms) SELECT `orders`.* FROM `orders` WHERE `orders`.`id` = 24 LIMIT 1=>#<订单id:24,user_id:1,order_date:nil,total_cents:0,total_currency:USD",shipping_cents:0,shipping_currency:USD",tax_cents:0,tax_currency:USD",subtotal_cents:0,subtotal_currency: "USD", created_at: "2014-06-13 21:24:38", updated_at: "2014-06-13 21:24:38", status: "Incomplete",coupon_id: nil>irb(main):005:0>o.updated_at=>2014 年 6 月 13 日星期五 21:24:38 UTC +00:00
我关心这个的原因是因为我用 ActiveRecord::Base.transaction
包装了一个函数的内部,所以我想测试它们在出现问题时没有更新:>
Rspec 测试(在不应该通过的时候一直通过,因为无论成功还是失败,updated_at 都不会改变):
它回滚事务"做...order.stub(:save!).and_raise(StandardError)期望{ payment_info.save }.not_to change { [billing_address.updated_at,shipping_address.updated_at,order.user.updated_at,order.updated_at] }结尾
还有我的方法:
def process_billing_info!ActiveRecord::Base.transaction 做billing_address.save!送货地址.保存!用户.保存!order.update_all_fees!结尾救援异常 =>电子错误的结尾
正如您在日志中看到的那样,没有执行 UPDATE
SQL 查询.Rails 根本没有更新您的记录.这是因为 .save
实际上仅在进行更改时才保存记录.
有方法 .touch
(文档) 您可以调用它来更新 updated_at
字段,而无需更改您的记录:
1.9.3p489 :005 >干预第一接触干预负载 (12.9ms) SELECT interventions".* FROM interventions"限制 1SQL (20.5ms) UPDATE interventions"设置updated_at"= '2014-06-18 16:34:03.924648' WHERE interventions". id"= 1=>真的
这里我们看到了 UPDATE
SQL 查询.
I always thought .save
and .save!
would update the updated_at
column of existing records. Is this not true? If so, then do I need to create a before_save filter to update it everytime I save?
Today is June 18th:
Loading development environment (Rails 4.1.1)
irb(main):001:0> o = Order.last
Order Load (0.4ms) SELECT `orders`.* FROM `orders` ORDER BY `orders`.`id` DESC LIMIT 1
=> #<Order id: 24, user_id: 1, order_date: nil, total_cents: 0, total_currency: "USD", shipping_cents: 0, shipping_currency: "USD", tax_cents: 0, tax_currency: "USD", subtotal_cents: 0, subtotal_currency: "USD", created_at: "2014-06-13 21:24:38", updated_at: "2014-06-13 21:24:38", status: "Incomplete", coupon_id: nil>
irb(main):002:0> o.save!
(0.4ms) BEGIN
(0.3ms) COMMIT
=> true
irb(main):003:0> o.updated_at
=> Fri, 13 Jun 2014 21:24:38 UTC +00:00
irb(main):004:0> o.reload
Order Load (0.7ms) SELECT `orders`.* FROM `orders` WHERE `orders`.`id` = 24 LIMIT 1
=> #<Order id: 24, user_id: 1, order_date: nil, total_cents: 0, total_currency: "USD", shipping_cents: 0, shipping_currency: "USD", tax_cents: 0, tax_currency: "USD", subtotal_cents: 0, subtotal_currency: "USD", created_at: "2014-06-13 21:24:38", updated_at: "2014-06-13 21:24:38", status: "Incomplete", coupon_id: nil>
irb(main):005:0> o.updated_at
=> Fri, 13 Jun 2014 21:24:38 UTC +00:00
The reason I care about this is because I am wrapping the internals of a function with ActiveRecord::Base.transaction
so I want to test that they are not updated when something goes wrong:
Rspec test (that passes all the time when it's not supposed to, since updated_at isn't being changed regardless of success or failure):
it "rollsback the transaction" do
...
order.stub(:save!).and_raise(StandardError)
expect { payment_info.save }.not_to change { [billing_address.updated_at,
shipping_address.updated_at,
order.user.updated_at,
order.updated_at] }
end
And my method:
def process_billing_info!
ActiveRecord::Base.transaction do
billing_address.save!
shipping_address.save!
user.save!
order.update_all_fees!
end
rescue Exception => e
false
end
As you can see in your log, there is no UPDATE
SQL query that is executed. Rails is not updating your record at all. This is because .save
actually saves the record only if changes were made.
There is the method .touch
(Documentation) that you can call in order to update the updated_at
field without having to do changes to your record:
1.9.3p489 :005 > Intervention.first.touch
Intervention Load (12.9ms) SELECT "interventions".* FROM "interventions" LIMIT 1
SQL (20.5ms) UPDATE "interventions" SET "updated_at" = '2014-06-18 16:34:03.924648' WHERE "interventions"."id" = 1
=> true
Here we see the UPDATE
SQL query.
这篇关于Rails 4:.save 不会更新现有记录的 updated_at?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!