Reputation: 4050
In my app I have teams and each team has a game time every week. I want the game times to be set to 'now' as a default. My table is set up like so
create_table "teams", force: true do |t|
t.datetime "wk1_time"
end
I created a migration and it looks like this:
class ChangeDateTimeDefault < ActiveRecord::Migration
def change
change_column :teams, :wk1_time, :default => DateTime.now
end
end
When I run rake db:migrate I get an error. Is my syntax wrong or am I missing something else?
Upvotes: 14
Views: 22035
Reputation: 2800
in rails 7 you should do the following (in case you want your timestamp to be evaluated each time when the row is being inserted)
db/migrate/20240215142705_alter_table_teams.rb
add_column :teams, :wk1_time, :timestamp, null: false, default: -> { "now()" }
which results the follwing structure
wk1_time timestamp without time zone DEFAULT now() NOT NULL
Upvotes: 0
Reputation: 7
This works for me:
class MigrationName < ActiveRecord::Migration[7.0]
def change
add_column :table_name, :column_name, :integer, default: 100, null: false
add_column :table_name, :column_name_date_to_save, :datetime, default: DateTime.now
end
end
Upvotes: -1
Reputation: 40770
EDIT: For Rails 5+ there are better answers, like this one: https://stackoverflow.com/a/55357711/252799, though the below still works.
The way I found, was to do a migration on an existing datetime column, like this:
#migration
execute("ALTER TABLE teams ALTER COLUMN wk1_time SET DEFAULT CURRENT_TIMESTAMP")
that produces a schema.rb entry shown like this:
#schema.rb
t.datetime "wk1_time", default: "now()", null: false
The "now()"
is a string sent to postgresql and evaluated at runtime, upon each insert.
Upvotes: 8
Reputation: 2820
Since Rails 5 you can make a migration like this:
change_column_default :users, :wk1_time, -> { 'CURRENT_TIMESTAMP' }
In my mind this is the best option because it not database specific answer.
Upvotes: 24
Reputation: 3169
for Postgresql :
add_column :users, :msgs_seen_at, 'TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP'
but you'll have to use user.reload
after user = User.create
in order to "see" msgs_seen_at
Upvotes: 1
Reputation: 118261
Yes, you are missing the type :
class ChangeDateTimeDefault < ActiveRecord::Migration
def change
change_column :teams, :wk1_time, :datetime, :default => DateTime.now
end
end
But, you need the below not the above one, because you just want to change the default.
class ChangeDateTimeDefault < ActiveRecord::Migration
def change
change_column_default :teams, :wk1_time, DateTime.now
end
end
But none of these are correct approach for your task. The reason is DateTime.now
will be evaluated based upon when you ran the migration, instead when the record is created. You need look to into this answer to know how to set the default time.
Upvotes: 13
Reputation: 43815
You're going to run into problems settings the default date time in the migration. This is because DateTime.now
will be evaluated based upon when the migrate runs, not when the record is created!
To fix that you'll need to create an ActiveRecord callback in order to set wk1_time
like so:
before_create :set_default_wk1_datetime
def set_default_wk1_datetime
self.wk1_time = DateTime.now
end
Upvotes: 4