5

Rails 7 allows setting timestamps on insert_all/upsert_all record creation

 2 years ago
source link: https://blog.saeloun.com/2022/01/18/rails-7-updates-timestamp-for-insert-and-upsert-all-queries
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Rails 7 allows setting timestamps on insert_all/upsert_all record creation

Jan 18, 2022 , by Swaathi Kakarla

1 minute read

ActiveRecord is one of the most useful utilities in the Rails toolkit. It allows us to perform complex database queries while abstracting the adapter, essentially making a database “pluggable”.

However, some edge cases stand out like a sore thumb. One such query is the ability to set values to the standard Rails timestamps which are available across models. Namely, created_at, created_on, updated_at, updated_on.

In a typical model insertion, one does not need to actively set values for the timestamps. They are set by the underlying framework at the time of insertion.

> Book.create(title: "Ruby on Rails Tutorial: Learn Web Development with Rails")

> Book.last.created_at
=> Tue, 18 Jan 2022

Before

One would expect consistent action across similar queries. Let’s have a look at mass insertion queries.

> Book.insert_all[
  {title: "Ruby on Rails Tutorial: Learn Web Development with Rails"},
  {title: "Service-Oriented Design with Ruby and Rails"}
]

=> Traceback (most recent call last):
        1: from (irb):1
ActiveRecord::NotNullViolation (SQLite3::ConstraintException: NOT NULL constraint failed: books.created_at)

It raises an unexpected exception ActiveRecord::NotNullViolation, since a database constraint is present on the created_at column. This leaves us with only one option — manually providing values for all timestamp columns.

The only way to make this work is,

> Book.insert_all[
  {title: "Ruby on Rails Tutorial: Learn Web Development with Rails", created_at: Time.now, updated_at: Time.now},
  {title: "Service-Oriented Design with Ruby and Rails", created_at: Time.now, updated_at: Time.now}
]

=> #<ActiveRecord::Result:0x00007f9ffcdfb620 @columns=[], @rows=[], @hash_rows=nil, @column_types={}>

After

Fortunately, Rails 7 allow setting timestamps on insert_all / upsert_all record queries.

> Book.insert_all[
  {title: "Ruby on Rails Tutorial: Learn Web Development with Rails"},
  {title: "Service-Oriented Design with Ruby and Rails"}
]

=> #<ActiveRecord::Result:0x00007f9ffcdfb620 @columns=[], @rows=[], @hash_rows=nil, @column_types={}>

We have the option to override this configuration using,

> Book.insert_all[
  {title: "Ruby on Rails Tutorial: Learn Web Development with Rails"},
  {title: "Service-Oriented Design with Ruby and Rails"}
], record_timestamps: false

=> Traceback (most recent call last):
        1: from (irb):1
ActiveRecord::NotNullViolation (SQLite3::ConstraintException: NOT NULL constraint failed: books.created_at)

Which, as expected, will result in the previous error.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK