我一直认为.save
和.save!
会更新现有记录的updated_at
列。这不是真的吗?如果是这样,那么每次保存时我是否需要创建一个before_save过滤器来更新它?
今天是6月18日:
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
我关心这个的原因是因为我用ActiveRecord::Base.transaction
包裹了一个函数的内部结构,所以我想测试一下出现问题时它们没有更新:
Rspec测试(当它不应该时,它会一直传递,因为无论成功或失败都没有更改updated_at):
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
我的方法:
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
答案 0 :(得分:15)
正如您在日志中看到的那样,没有执行UPDATE
SQL查询。 Rails根本没有更新你的记录。这是因为.save
实际只有在对该记录进行了更改时才会保存记录。
您可以调用.touch
方法来更新updated_at
字段,而无需对记录进行更改:
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
在这里,我们看到UPDATE
SQL查询。
答案 1 :(得分:2)
与@ MrYoshiji的回答相配,这是使用.touch
的另一种方式:
if o.save!
o.touch unless o.changed?
end