如何在迁移脚本中设置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_at
或created_on
的date时间列,ActiveRecord将“神奇地”将其设置为创builddate时间。 你不需要做任何事情,除了拥有这个专栏。
您也可以拥有updated_at
或updated_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