Pertanyaan Bagaimana cara menetapkan nilai default untuk kolom datetime dalam skrip migrasi?


Pertimbangkan skrip pembuatan tabel di bawah ini:

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

Apakah mungkin untuk menetapkan nilai default sebagai waktu saat ini?

Saya mencoba mencari DB independen yang setara dalam rel untuk definisi kolom SQL yang diberikan di bawah ini:

Oracle Syntax

start_at DATE DEFAULT SYSDATE() 

Sintaks MySQL

start_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP

ATAU

start_at DATETIME DEFAULT NOW()

81
2017-10-16 22:54


asal


Jawaban:


Ini didukung sekarang di Rails 5.

Berikut ini contoh migrasi:

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

Lihat diskusi di https://github.com/rails/rails/issues/27077 dan jawab di sana dengan prathamesh-sonpatki


111
2017-11-17 05:14



Anda dapat menambahkan fungsi dalam model seperti ini:

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

Sehingga model akan mengatur waktu saat ini dalam model.

Anda juga dapat menempatkan beberapa kode sql dalam migrasi untuk menetapkan nilai default pada tingkat basis data, sesuatu seperti:

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

Mengatur sesuatu seperti ini:

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

menyebabkan mengeksekusi fungsi Time.now saat bermigrasi sehingga kemudian tabel dalam basis data dibuat seperti ini:

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

tapi saya pikir itu bukan yang Anda inginkan.


110
2017-10-16 23:11



Jika Anda memiliki kolom datetime disebut created_at atau created_on, ActiveRecord akan 'secara ajaib' mengaturnya ke waktu pembuatan. Anda tidak perlu melakukan hal lain kecuali memiliki kolom itu.

Anda juga bisa updated_at atau updated_on dan itu akan diperbarui ketika catatan diperbarui.


12
2017-10-17 02:01



Saya mencari solusi yang serupa tetapi saya akhirnya menggunakan https://github.com/FooBarWidget/default_value_for.

Itu default_value_for Plugin memungkinkan seseorang untuk menentukan nilai default untuk model ActiveRecord dengan cara deklaratif. Sebagai contoh:

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

9
2018-06-01 14:26



Saya biasanya melakukan:

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

Jadi, kamu schema.rb akan memiliki sesuatu seperti:

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

7
2018-06-03 10:43



Jika perlu perubahan sebuah kolom DateTime yang ada di Rails 5 (daripada membuat tabel baru sebagaimana ditentukan dalam jawaban lain) sehingga dapat memanfaatkan kemampuan tanggal default, Anda dapat membuat migrasi seperti ini:

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

2
2017-09-07 19:07



On Rails 5.1

class CreateClients < ActiveRecord::Migration[5.1]
  def change
    create_table :cars do |t|
      *******************************
      t.datetime :starts_at, :null => false, default: -> {'CURRENT_TIMESTAMP'}
      *******************************
      t.timestamps
    end
  end
end

0
2018-04-09 09:22