9

Sorry if this has been answered before but I can't find a definite answer.

Surely someone has come across this issue when using upsert you need to specify every column including created_at and updated_at?

How can I not update the created_at timestamp when an upsert happens? I only want to insert created_at once.

a = User.upsert({
          name: ....,
          age: ....
          created_at: DateTime.now, 
          updated_at: DateTime.now
        }, unique_by: :upsert_user_index )
i cant code
  • 305
  • 2
  • 7

2 Answers2

10

Update Existing tables with defaults:

change_column :table_foos, :created_at, :datetime, null: false, default: -> { "CURRENT_TIMESTAMP" }
change_column :table_foos, :updated_at, :datetime, null: false, default: -> { "CURRENT_TIMESTAMP" }

Create NEW tables with defaults:

create_table :table_foos do |t|
  # date with timestamp
  t.datetime :last_something_at, null: false, default: -> { "CURRENT_TIMESTAMP" }
  
  # standard timestamps
  t.timestamps default: -> { "CURRENT_TIMESTAMP" }
end
Lev Lukomsky
  • 6,346
  • 4
  • 34
  • 24
Blair Anderson
  • 19,463
  • 8
  • 77
  • 114
5

No need to provide created_at and updated_at if you had already set the default value i.e. now() in the db. It will automatically takes the current timestamp.

a = User.upsert({
          name: ....,
          age: ....,
          created_at: Time.now,
          updated_at:Time.now
          
        }, nil, unique_by: :upsert_user_index )

But if you want to insert a single record, you should use create or save. It will trigger the validations and callbacks. And if you want to skip them, you can do as well. You should use upsert_all if want to insert multiple entries in single sql without callbacks and validations.

Chakreshwar Sharma
  • 2,571
  • 1
  • 11
  • 35
  • 1
    `upsert` typically does require `created_at` and `updated_at` as they typically have non-null constraints in the database. You're right about just using create or save instead. – Bill Doughty Jul 15 '20 at 17:08