代码之家  ›  专栏  ›  技术社区  ›  Harish Shetty

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

  •  93
  • Harish Shetty  · 技术社区  · 15 年前

    请考虑下面的表创建脚本:

    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
    

    start_at DATETIME DEFAULT NOW()
    
    7 回复  |  直到 6 年前
        1
  •  133
  •   Will    8 年前

    现在在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 答案是普拉塔梅什·桑帕基

        2
  •  114
  •   Szymon Lipiński    15 年前

    您可以在这样的模型中添加函数:

      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');
    

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

        3
  •  12
  •   Ryan Bigg Andrés Bonilla    15 年前

    如果您有一个名为 created_at created_on ,ActiveRecord将“神奇地”将其设置为创建日期时间。您不需要做任何其他事情,只需要拥有该列。

    你也可以 updated_at updated_on 当一个记录被更新时,它会被更新。

        4
  •  9
  •   Giovanni Cappellotto azamsharp    12 年前

    我在寻找类似的解决方案,但我最终使用了 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
    
        5
  •  8
  •   Arturo Herrero Viren    8 年前

    我通常这样做:

    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
    
        6
  •  3
  •   Matt Long    7 年前

    如果你需要 改变 现有日期时间列 在Rails 5中(而不是创建其他答案中指定的新表),这样它就可以利用默认的日期功能,您可以创建如下迁移:

    class MakeStartsAtDefaultDateForFoo < ActiveRecord::Migration[5.0]
      def change
        change_column :foos, :starts_at, :datetime, default: -> { 'CURRENT_TIMESTAMP' }
      end
    end
    
        7
  •  -1
  •   Sony Mathew    8 年前

    在@szymon lipi_ski(szymon lipi_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