Ruby-on-rails 如何为日期时间列设置默认值以记录迁移中的创建时间?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1580805/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 21:52:14  来源:igfitidea点击:

How to set a default value for a datetime column to record creation time in a migration?

ruby-on-rails

提问by Harish Shetty

Consider the table creation script below:

考虑下面的表创建脚本:

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

Is it's possible to set the default value as the current time?

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

I am trying to find a DB independent equivalent in rails for the SQL column definitions given below:

我正在尝试为下面给出的 SQL 列定义在 rails 中找到一个独立于数据库的等效项:

Oracle Syntax

甲骨文语法

start_at DATE DEFAULT SYSDATE() 

MySQL Syntax

MySQL 语法

start_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP

OR

或者

start_at DATETIME DEFAULT NOW()

回答by Will

This is supported now in Rails 5.

这在 Rails 5 中现在得到支持。

Here is a sample migration:

这是一个示例迁移:

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

See discussion at https://github.com/rails/rails/issues/27077and answer there by prathamesh-sonpatki

请参阅https://github.com/rails/rails/issues/27077 上的讨论,并由 prathamesh-sonpatki 回答

回答by Szymon Lipiński

You can add a function in a model like this:

您可以在模型中添加一个函数,如下所示:

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

So that the model will set the current time in the model.

这样模型就会在模型中设置当前时间。

You can also place some sql code in the migration for setting the default value at the database level, something like:

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

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

Setting something like this:

设置如下:

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

causes executing the Time.now function during migrating so then the table in database is created like this:

导致在迁移期间执行 Time.now 函数,因此数据库中的表是这样创建的:

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

but I think that it is not what you want.

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

回答by Jim

Active Record automatically timestamps create and update operations if the table has fields named created_at/created_onor updated_at/updated_on. Source - api.rubyonrails.org

如果表具有名为created_at/created_onupdated_at/ 的字段,则 Active Record 会自动为创建和更新操作添加时间戳updated_on来源 - api.rubyonrails.org

You don't need to do anything else except to have that column.

除了拥有该列之外,您无需执行任何其他操作。

回答by Giovanni Cappellotto

I was searching for a similar solutions but I ended using https://github.com/FooBarWidget/default_value_for.

我正在寻找类似的解决方案,但我最终使用了https://github.com/FooBarWidget/default_value_for

The default_value_forplugin allows one to define default values for ActiveRecord models in a declarative manner. For example:

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

回答by Arturo Herrero

I usually do:

我通常这样做:

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

So, your schema.rbis going to have something like:

所以,你schema.rb将有类似的东西:

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

回答by Matt Long

If you need to changean existing DateTime columnin Rails 5 (rather than creating a new table as specified in other answers) so that it can take advantage of the default date capability, you can create a migration like this:

如果您需要更改现有DateTime列在导轨5(而不是在其他的答案中指定创建新表),以便它可以采取默认的日期能力的优势,你可以创建一个这样的迁移:

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

回答by Sony Mathew

In the answer given by @szymon-lipiński (Szymon Lipiński), the execute method didn't work for me. It was throwing a MySQL syntax error.

在@szymon-lipiński (Szymon Lipiński) 给出的答案中,execute 方法对我不起作用。它抛出了一个 MySQL 语法错误。

The MySQL syntax which worked for me is this.

对我有用的 MySQL 语法是这样的。

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

So to set the default value for a datetime column in migration script can be done as follows:

因此,要在迁移脚本中为日期时间列设置默认值,可以按如下方式完成:

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