Как установить значение по умолчанию для столбца datetime, чтобы записать время создания в миграции?
Рассмотрим создание таблицы script ниже:
create_table :foo do |t|
t.datetime :starts_at, :null => false
end
Можно ли установить значение по умолчанию в качестве текущего времени?
Я пытаюсь найти DB независимый эквивалент в rails для определений столбцов SQL, приведенных ниже:
Синтаксис Oracle
start_at DATE DEFAULT SYSDATE()
Синтаксис MySQL
start_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
ИЛИ
start_at DATETIME DEFAULT NOW()
Ответы
Ответ 1
Теперь это поддерживается в 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
Вы можете добавить функцию в такую модель:
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
Если у вас есть столбец datetime с именем created_at
или created_on
, ActiveRecord "волшебным образом" настроит его на дату создания. Вам не нужно ничего делать, кроме как иметь этот столбец.
Вы также можете иметь updated_at
или updated_on
, и он будет обновляться при обновлении записи.
Ответ 4
Я искал похожие решения, но я закончил использование 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
Я обычно делаю:
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
Если вам нужно изменить существующий столбец DateTime в Rails 5 (вместо создания новой таблицы, как указано в других ответах), чтобы он мог использовать возможность по умолчанию для даты, вы можете создать миграция:
class MakeStartsAtDefaultDateForFoo < ActiveRecord::Migration[5.0]
def change
change_column :foos, :starts_at, :datetime, default: -> { 'CURRENT_TIMESTAMP' }
end
end
Ответ 7
На 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
Ответ 8
В ответе @szymon-lipiński (Szymon Lipiński) метод выполнения не работал у меня. Это метало ошибку синтаксиса MySQL.
Синтаксис MySQL, который работал у меня, это.
execute "ALTER TABLE mytable CHANGE `column_name` `column_name` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP"
Итак, чтобы установить значение по умолчанию для столбца datetime в миграции script, можно сделать следующее:
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