Ruby-on-rails 有没有办法避免自动更新 Rails 时间戳字段?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/861448/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 21:14:54  来源:igfitidea点击:

Is there a way to avoid automatically updating Rails timestamp fields?

ruby-on-railsrubyactiverecordtimestamp

提问by Ethan

If you have DB columns created_atand updated_atRails will automatically set those values when you create and update a model object. Is there a way to save the model without touching those columns?

如果您有 DB 列created_atupdated_atRails 会在您创建和更新模型对象时自动设置这些值。有没有办法在不触及这些列的情况下保存模型?

I am bringing in some legacy data and I would like to set those values from the corresponding values in the (differently named) legacy data fields. I'm finding when I set them on the model and then save the model, Rails appears to override the incoming values.

我正在引入一些遗留数据,我想从(不同命名的)遗留数据字段中的相应值中设置这些值。我发现当我在模型上设置它们然后保存模型时,Rails 似乎覆盖了传入的值。

Of course I could just name the Rails model columns differently to prevent that, but after the data is imported, I want Rails to do its automatic timestamp thing.

当然,我可以对 Rails 模型列进行不同的命名以防止这种情况发生,但在导入数据后,我希望 Rails 自动执行时间戳操作。

回答by August Lilleaas

Do this in a migration or in a rake task (or in the new database seedsif you're on edge rails):

在迁移或 rake 任务中执行此操作(如果您在边缘导轨上,则在新的数据库种子中执行此操作):

ActiveRecord::Base.record_timestamps = false
begin
  run_the_code_that_imports_the_data
ensure
  ActiveRecord::Base.record_timestamps = true  # don't forget to enable it again!
end

You can safely set created_atand updated_atmanually, Rails won't complain.

您可以安全地设置created_atupdated_at手动,Rails会不会抱怨。

Note: This also works on individual models, e.g. User.record_timestamps = false

注意:这也适用于单个模型,例如 User.record_timestamps = false

回答by yawl

use update_column method instead:

改用 update_column 方法:

http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-update_column

http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-update_column

update_column(name, value)
# Updates a single attribute of an object, without calling save.

Validation is skipped.

跳过验证。

Callbacks are skipped.

回调被跳过。

updated_at/updated_on column is not updated if that column is available.

如果该列可用,则 updated_at/updated_on 列不会更新。

Raises an ActiveRecordError when called on new objects, or when the name attribute is marked as readonly.

在新对象上调用时,或当 name 属性被标记为只读时,引发 ActiveRecordError。

回答by Subhash Chandra

Rails 5 provides a convenient way to update a record without updating it's timestamp updated_at: https://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-save

Rails 5 提供了一种无需更新时间戳即可更新记录的便捷方法updated_athttps: //api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-save

You, just need to pass touch:falsewhile updating your record.

你,只需要touch:false在更新你的记录时通过。

>> user = User.first
>> user.updated_at
=> Thu, 28 Apr 2016 20:01:57 IST +05:30
>> user.name = "Jose"
>> user.save(touch: false)
=> true

>> user.updated_at
=> Thu, 28 Apr 2016 20:01:57 IST +05:30

回答by Toby Hede

You can set the following inside your migration:

您可以在迁移中设置以下内容:

ActiveRecord::Base.record_timestamps = false

Or altenatively use update_all:

或者也可以使用 update_all:

update_all(updates, conditions = nil, options = {})

Updates all records with details given if they match a set of conditions supplied, limits and order can also be supplied. This method constructs a single SQL UPDATE statement and sends it straight to the database. It does not instantiate the involved models and it does not trigger Active Record callbacks.

update_all(更新,条件 = 零,选项 = {})

如果所有记录与提供的一组条件匹配,则使用给出的详细信息更新所有记录,也可以提供限制和顺序。此方法构造单个 SQL UPDATE 语句并将其直接发送到数据库。它不会实例化所涉及的模型,也不会触发 Active Record 回调。

回答by Chuck Batson

In Rails 3+, for a single object, set record_timestampsfor the object rather than class. I.e.,

在 Rails 3+ 中,对于单个对象,设置record_timestamps为对象而不是类。IE,

>> user = User.first
>> user.updated_at
=> Tue, 12 Apr 2016 22:47:51 GMT +00:00
>> user.name = "Jose"
=> "Jose"
>> user.record_timestamps = false
>> user.save
=> true
>> user.updated_at
=> Tue, 12 Apr 2016 22:47:51 GMT +00:00
>> User.record_timestamps
=> true

This way, you don't touch global state for the model, and you don't have to remember to restore the prior setting in an ensureblock.

这样,您就不会触及模型的全局状态,也不必记住恢复ensure块中的先前设置。

回答by runako

Since this is a one-time import, you could do the following:

由于这是一次性导入,您可以执行以下操作:

  1. Create model using legacy_created_atand legacy_updated_atfields.
  2. Load legacy data. Map into the model fields as desired. You can use #saveand generally not worry about using update_allor the like, and you can use callbacks if desired.
  3. Create a migration to rename the columns to created_atand updated_at.
  1. 使用legacy_created_atlegacy_updated_at字段创建模型。
  2. 加载旧数据。根据需要映射到模型字段。您可以使用#save并且一般不用担心使用update_all等,如果需要,您可以使用回调。
  3. 创建迁移以将列重命名为created_atupdated_at

回答by nonrectangular

I like to use a mixin module to temporarily turn off time-stamping in a block:

我喜欢使用 mixin 模块暂时关闭块中的时间戳:

module WithoutTimestamps
  def without_timestamps
    old = ActiveRecord::Base.record_timestamps
    ActiveRecord::Base.record_timestamps = false
    begin
      yield
    ensure
      ActiveRecord::Base.record_timestamps = old
    end
  end
end

Then you can use it wherever you need it

然后你可以在任何需要的地方使用它

class MyModel < ActiveRecord::Base
  include WithoutTimestamps

  def save_without_timestamps
    without_timestamps do
      save!
    end
  end
end

Or just a one-off like this:

或者只是这样的一次性:

m = MyModel.find(1)
WithoutTimestamps.without_timestamps do
  m.save!
end

回答by Christer Fernstrom

Referring to other answers, I found to my surprise that disabling timestamps for a single model, like in:

参考其他答案,我惊讶地发现禁用单个模型的时间戳,例如:

User.record_timestamps = false

worked for my development database, but not on my pre-production database, which runs on a different server. However it works if I disable timestamps for all models with

适用于我的开发数据库,​​但不适用于在不同服务器上运行的预生产数据库。但是,如果我禁用所有模型的时间戳,它会起作用

ActiveRecord::Base.record_timestamps = false

(Situation: modifying the created_at attribute in a migration)

(情况:在迁移中修改 created_at 属性)

回答by iwiznia

When not in a bulk import, you can override the should_record_timestamps? method on your model to add new checks on when to update the updated_at column.

当不在批量导入中时,您可以覆盖 should_record_timestamps? 模型上的方法来添加有关何时更新 updated_at 列的新检查。