在 Rails 迁移中,如何将列的默认值设置为 NOW() 而不是运行迁移的时间? [英] In a Rails migraiton, how do I set the default value of a column to be NOW() instead of the time when I ran the migration?

查看:66
本文介绍了在 Rails 迁移中,如何将列的默认值设置为 NOW() 而不是运行迁移的时间?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 PostGres 9.4 数据库.我想将 DATETIME 列的默认列类型更改为创建记录的时间.我认为这是正确的方法,因为这是我的 Rails 迁移

I have a PostGres 9.4 database. I want to change the default column type of a DATETIME column to be the time when the record was created. I thought this was the right way, in as far as this is my rails migration

class ChangeDefaultValueForStratumWorkerSubmissions < ActiveRecord::Migration[5.1]
  def change
    change_column_default(:stratum_worker_submissions, :created_at, 'NOW')
  end
end

但是当我查看我的数据库时,默认时间戳显示为我运行迁移的时间,而不是我想要的表达式.我如何编写一个可以满足我要求的迁移?

but when I look at my database, the default timestamp shows as the time when I ran the migration, instead of the expression I want. How do I write a migration that will do what I want?

      Column       |            Type             |                                 Modifiers
-------------------+-----------------------------+----------------------------------------------------------------------------
 id                | integer                     | not null default nextval('stratum_worker_submissions_id_seq'::regclass)
 stratum_worker_id | integer                     |
 created_at        | timestamp without time zone | not null default '2018-04-04 19:46:22.781613'::timestamp without time zone

推荐答案

它没有很好的文档记录,但您可以提供一个 lambda 作为迁移中的默认值,这将做正确的事情.如果你这样说:

It isn't well documented but you can supply a lambda as the default value in a migration and that will do The Right Thing. If you say this:

def change
  change_column_default :stratum_worker_submissions, :created_at, -> { 'now()' }
end

那么该列的默认值将被设置为 now() 并且数据库函数 now() 不会被调用,直到该列需要一个默认值.然后如果你在 psql\d stratum_worker_submissions 你会看到:

then the column's default value will be set to now() and the database function now() won't be called until a default value is needed for the column. Then if you \d stratum_worker_submissions in psql you'll see:

created_at | timestamp without time zone | not null default now()

根据需要.迁移运行时将评估任何其他默认值,您最终将使用固定时间戳作为默认值.

as desired. Any other default will be evaluated when the migration runs and you'll end up with a fixed timestamp as the default.

或者,您始终可以使用 SQL 手动完成:

Alternatively, you can always do it by hand using SQL:

def up
  connection.execute(%q(
    alter table stratum_worker_submissions
    alter column created_at
    set default now()
  ))
end
def down
  connection.execute(%q(
    alter table stratum_worker_submissions
    alter column created_at
    drop default
  ))
end

请注意,如果您开始使用 SQL 手动更改架构,您可能会开始做一些不会出现在 db/schema.rb 中的事情,因为您可以快速进入 ActiveRecord 不理解的 SQL.如果发生这种情况,您可以通过更改 config/application.rbdb/schema.rb 更改为 db/structure.sql :

Note that if you start manually changing the schema with SQL you might start doing things that won't appear in db/schema.rb as you can quickly get into SQL that ActiveRecord doesn't understand. If that happens then you can change from db/schema.rb to db/structure.sql by changing config/application.rb:

config.active_record.schema_format = :sql

然后在版本控制中用 db/structure.sql 替换 db/schema.rb 并使用 db:structure rake 任务通常 db:schema 任务的位置.

and then replacing db/schema.rb with db/structure.sql in revision control and using the db:structure rake tasks in place of the usual db:schema tasks.

这篇关于在 Rails 迁移中,如何将列的默认值设置为 NOW() 而不是运行迁移的时间?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆