You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Try to manipulate time around insert_all or upsert_all to observe varying timestamps.
# frozen_string_literal: truerequire"bundler/inline"gemfile(true)dosource"https://rubygems.org"gem"rails"# If you want to test against edge Rails replace the previous line with this:# gem "rails", github: "rails/rails", branch: "main"gem"sqlite3","~> 1.4"gem"timecop"endrequire"active_record"require"minitest/autorun"require"logger"# This connection will do for database-independent bug reports.ActiveRecord::Base.establish_connection(adapter: "sqlite3",database: ":memory:")ActiveRecord::Base.logger=Logger.new(STDOUT)ActiveRecord::Schema.definedocreate_table:posts,force: truedo |t|
t.timestampsendendclassPost < ActiveRecord::Basehas_many:commentsendclassBugTest < Minitest::Test# Failsdeftest_upsert_all_timestampPost.upsert_all[{id: 101}]Timecop.freeze(Date.today + 3.days)doPost.upsert_all[{id: 102}]alice=Post.find(101)bob=Post.find(102)assert(bob.created_at.to_date - alice.created_at.to_date).to_i >= 2endend# Succeedsdeftest_standard_creationalice=Post.create!(id: 103)Timecop.freeze(Date.today + 3.days)dobob=Post.create!(id: 104)assert(bob.created_at.to_date - alice.created_at.to_date).to_i >= 2endendend
Expected behavior
I would expect the timestamps to be set and follow the same rules as the standard creation/update.
Actual behavior
Timestamps within insert_all, upsert_all are set using a DB function to get the current time, thus not behaving the same way nor being impacted by utilities like Timecop or travel_to.
Potential fix
If this behaviour is not intended, I think relying on the model current_time_from_proper_timezone to build timestamps in ActiveRecord::InsertAll could be a solution.
Would be happy to contribute!
System configuration
Rails version: 7.1.3.2
Ruby version: 3.3
The text was updated successfully, but these errors were encountered:
srozen
changed the title
Different Timestamp behaviour with InsertAll
Different timestamps behaviour with InsertAll
May 14, 2024
Well, you could do Post.upsert_all [{ id: 102, created_at: Time.current}].
For multiple reasons, it's so great that we have methods (e.g. upsert_all) that totally skip record instantiation and go straight to the DB and use native functions (NOW in this case).
If your logic depends on time, then I would use create (e.g. User.create([{ first_name: 'Jamie' }, { first_name: 'Jeremy' }])) instead of insert_all.
Steps to reproduce
Try to manipulate time around
insert_all
orupsert_all
to observe varying timestamps.Expected behavior
I would expect the timestamps to be set and follow the same rules as the standard creation/update.
Actual behavior
Timestamps within
insert_all
,upsert_all
are set using a DB function to get the current time, thus not behaving the same way nor being impacted by utilities likeTimecop
ortravel_to
.Potential fix
If this behaviour is not intended, I think relying on the model
current_time_from_proper_timezone
to build timestamps inActiveRecord::InsertAll
could be a solution.Would be happy to contribute!
System configuration
Rails version: 7.1.3.2
Ruby version: 3.3
The text was updated successfully, but these errors were encountered: