Rails 4:.save 不会更新现有记录的 updated_at? [英] Rails 4: .save does not update updated_at for existing records?

查看:34
本文介绍了Rails 4:.save 不会更新现有记录的 updated_at?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直认为 .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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆