如何在迁移脚本中设置date时间列的默认值?

考虑下面的表格创build脚本:

create_table :foo do |t| t.datetime :starts_at, :null => false end 

是否可以将默认值设置为当前时间?

我正在试图在下面给出的SQL列定义的rails中find一个DB独立的等价物:

Oracle语法

 start_at DATE DEFAULT SYSDATE() 

MySQL语法

 start_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP 

要么

 start_at DATETIME DEFAULT NOW() 

你可以在这样的模型中添加一个函数:

  before_create :set_foo_to_now def set_foo_to_now self.foo = Time.now end 

以便模型将设置模型中的当前时间。

您还可以在迁移中放置一些sql代码,以便在数据库级别设置默认值,如下所示:

 execute 'alter table foo alter column starts_at set default now()' 

设置这样的东西:

 create_table :foo do |t| t.datetime :starts_at, :null => false, :default => Time.now end 

导致在迁移期间执行Time.now函数,那么数据库中的表就像这样创build:

 create table foo ( starts_at timestamp not null default '2009-01-01 00:00:00'); 

但我认为这不是你想要的。

现在在Rails 5中支持。

这是一个示例迁移:

 class CreatePosts < ActiveRecord::Migration[5.0] def change create_table :posts do |t| t.datetime :modified_at, default: -> { 'CURRENT_TIMESTAMP' } t.timestamps end end end 

请参阅https://github.com/rails/rails/issues/27077的讨论,并通过prathamesh-sonpatki

如果你有一个名为created_atcreated_on的date时间列,ActiveRecord将“神奇地”将其设置为创builddate时间。 你不需要做任何事情,除了拥有这个专栏。

您也可以拥有updated_atupdated_on并在logging更新时更新。

我正在寻找类似的解决scheme,但我结束了使用https://github.com/FooBarWidget/default_value_for

default_value_for插件允许用声明的方式为ActiveRecord模型定义默认值。 例如:

 class User < ActiveRecord::Base default_value_for :name, "(no name)" default_value_for :last_seen do Time.now end end u = User.new u.name # => "(no name)" u.last_seen # => Mon Sep 22 17:28:38 +0200 2008 

我通常做:

 def change execute(" ALTER TABLE your_table ALTER COLUMN your_column SET DEFAULT CURRENT_TIMESTAMP ") end 

所以,你的schema.rb将会有这样的东西:

 create_table "your_table", force: :cascade do |t| t.datetime "your_column", default: "now()" end 

在@ szymon-lipiński(SzymonLipiński)给出的答案中,执行方法对我不起作用。 这是抛出一个MySQL语法错误。

为我工作的MySQL语法是这样的。

 execute "ALTER TABLE mytable CHANGE `column_name` `column_name` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP" 

所以在迁移脚本中设置datetime列的默认值可以做如下:

 def up create_table :foo do |t| t.datetime :starts_at, :null => false end execute "ALTER TABLE `foo` CHANGE `starts_at` `starts_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP" end 

如果您需要在Rails 5中更改 现有的DateTime列 (而不是像其他答案中指定的那样创build新表),以便利用缺省datefunction,可以创build如下所示的迁移:

 class MakeStartsAtDefaultDateForFoo < ActiveRecord::Migration[5.0] def change change_column :foos, :starts_at, :datetime, default: -> { 'CURRENT_TIMESTAMP' } end end