考虑下面的表创建脚本:
create_table :foo do |t|
t.datetime :starts_at, :null => false
end
是否可以将默认值设置为当前时间?
我试图在rails中为下面给出的SQL列定义找到数据库独立的等价物:
Oracle语法
start_at DATE DEFAULT SYSDATE()
MySQL语法
start_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
OR
start_at DATETIME DEFAULT NOW()
答案 0 :(得分:140)
现在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回答
答案 1 :(得分:114)
您可以在这样的模型中添加一个函数:
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函数,因此数据库中的表创建如下:
create table foo ( starts_at timestamp not null default '2009-01-01 00:00:00');
但我认为这不是你想要的。
答案 2 :(得分:12)
如果表具有名为created_at
/created_on
或updated_at
/updated_on
的字段,则Active Record会自动为时间戳创建和更新操作。 Source - api.rubyonrails.org
除了拥有该列之外,您不需要做任何其他事情。
答案 3 :(得分:9)
我正在寻找类似的解决方案但我最后使用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
答案 4 :(得分:9)
我通常会这样做:
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
答案 5 :(得分:5)
如果您需要在Rails 5中更改 现有DateTime列(而不是按照其他答案中的指定创建新表),以便它可以利用默认日期功能,您可以创建这样的迁移:
class MakeStartsAtDefaultDateForFoo < ActiveRecord::Migration[5.0]
def change
change_column :foos, :starts_at, :datetime, default: -> { 'CURRENT_TIMESTAMP' }
end
end
答案 6 :(得分:0)
你知道upserts fail unless you have a default updated_at/created_at
吗????
没有自动执行此操作的迁移标志,您必须手动包含带有 default
键的选项对象
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
答案 7 :(得分:-1)
在@ szymon-lipiński(SzymonLipiński)给出的答案中,执行方法对我不起作用。它抛出了MySQL语法错误。
对我有用的MySQL语法是这样的。
execute "ALTER TABLE mytable CHANGE `column_name` `column_name` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP"
因此,要在迁移脚本中设置日期时间列的默认值,请按以下步骤操作:
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