Відповіді:
Помічник часової позначки доступний лише у create_table
блоці. Ви можете додати ці стовпці, вказавши типи стовпців вручну:
class AddTimestampsToUser < ActiveRecord::Migration
def change_table
add_column :users, :created_at, :datetime, null: false
add_column :users, :updated_at, :datetime, null: false
end
end
Хоча це не має такого ж короткого синтаксису, як add_timestamps
метод, який ви вказали вище, Rails все одно буде розглядати ці стовпці як стовпчики часових позначок і нормально оновлювати значення.
rails g migration AddTimestampsToUser created_at:datetime updated_at:datetime
- ярлик для створення міграції вище.
PG::NotNullViolation: ERROR: column "created_at" contains null value
оскільки моя таблиця вже містить дані, що порушують ненулеві обмеження. Будь-який кращий спосіб зробити це, ніж спочатку видалити ненульовий контрант, а потім додати його згодом?
add_column :users, :updated_at, :datetime, null: false, default: Time.zone.now
. Time.zone.now
це лише приклад, ви повинні використовувати будь-яке значення, яке має сенс для вашої логіки.
Міграція - це лише два методи класу (або методи екземпляра в 3.1): up
і down
(а іноді change
метод екземпляра в 3.1). Ви хочете, щоб ваші зміни перейшли до up
методу:
class AddTimestampsToUser < ActiveRecord::Migration
def self.up # Or `def up` in 3.1
change_table :users do |t|
t.timestamps
end
end
def self.down # Or `def down` in 3.1
remove_column :users, :created_at
remove_column :users, :updated_at
end
end
Якщо вам 3,1, ви також можете використовувати change
(дякую Дейву):
class AddTimestampsToUser < ActiveRecord::Migration
def change
change_table(:users) { |t| t.timestamps }
end
end
Можливо , ти плутаєш def change
, def change_table
і change_table
.
change
метод зараз, хоча в цьому випадку не проблема :)
change
варто згадати, тому додам і цього.
Ваш оригінальний код дуже близький праворуч, вам просто потрібно використовувати іншу назву методу. Якщо ви використовуєте Rails 3.1 або новішої версії, вам потрібно визначити change
метод замість change_table
:
class AddTimestampsToUser < ActiveRecord::Migration
def change
add_timestamps(:users)
end
end
Якщо ви використовуєте старішу версію, вам потрібно визначитись up
і down
методи замість change_table
:
class AddTimestampsToUser < ActiveRecord::Migration
def up
add_timestamps(:users)
end
def down
remove_timestamps(:users)
end
end
@ user1899434 відповідь сприйняла той факт, що "існуюча" таблиця тут може означати таблицю з записами, які вже є в ній, записи, які ви, можливо, не хочете скидати. Тож коли ви додаєте часові позначки з null: false, що є типовим і часто бажаним, ці існуючі записи недійсні.
Але я думаю, що відповідь можна покращити, поєднавши два етапи в одну міграцію, а також за допомогою більш семантичного методу add_timestamps:
def change
add_timestamps :projects, default: Time.zone.now
change_column_default :projects, :created_at, nil
change_column_default :projects, :updated_at, nil
end
Ви можете замінити якусь іншу часову позначку DateTime.now
, наприклад, якщо ви хочете створити / оновити попередні записи на світанку часу.
Time.zone.now
це те, що слід використовувати, якщо ми хочемо, щоб наш код відповідав правильному часовому поясу.
Time.zone.now
якого він поверне екземпляр Time, який створюється під час виконання міграції, і просто використовувати цей час як за замовчуванням. Нові об'єкти не отримають новий екземпляр Time.
class AddTimestampsToUser < ActiveRecord::Migration
def change
change_table :users do |t|
t.timestamps
end
end
end
Доступні перетворення є
change_table :table do |t|
t.column
t.index
t.timestamps
t.change
t.change_default
t.rename
t.references
t.belongs_to
t.string
t.text
t.integer
t.float
t.decimal
t.datetime
t.timestamp
t.time
t.date
t.binary
t.boolean
t.remove
t.remove_references
t.remove_belongs_to
t.remove_index
t.remove_timestamps
end
http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/Table.html
Відповідь Ніка Девіса є найбільш повною з точки зору додавання стовпців часових позначок до таблиці з наявними даними. Єдиним його недоліком є те, що він підніметься ActiveRecord::IrreversibleMigration
на a db:rollback
.
Його слід модифікувати так, щоб він працював в обох напрямках:
def change
add_timestamps :campaigns, default: DateTime.now
change_column_default :campaigns, :created_at, from: DateTime.now, to: nil
change_column_default :campaigns, :updated_at, from: DateTime.now, to: nil
end
change_column_default
, не підтримує from
і to
в цій версії?), Але я взяв цю ідею і створив up/down
методи замість одного change
методу, і це спрацювало як шарм!
не впевнений, коли саме це було введено, але в рейках 5.2.1 ви можете це зробити:
class AddTimestampsToMyTable < ActiveRecord::Migration[5.2]
def change
add_timestamps :my_table
end
end
Докладніше див. " використання методу зміни " в документах про активні міграції записів.
, null: true
після:my_table
Я створив просту функцію, яку можна зателефонувати, щоб додати до кожної таблиці (якщо матимете наявну базу даних) поля create_at та updated_at :
# add created_at and updated_at to each table found.
def add_datetime
tables = ActiveRecord::Base.connection.tables
tables.each do |t|
ActiveRecord::Base.connection.add_timestamps t
end
end
add_timestamps (ім'я таблиці, параметри = {}) загальнодоступні
Додає стовпчики часу (створені_at та оновлені_at) стовпці. Додаткові параметри (як null: false) пересилаються до #add_column.
class AddTimestampsToUsers < ActiveRecord::Migration
def change
add_timestamps(:users, null: false)
end
end
Відповіді раніше здаються правильними, проте я зіткнувся з проблемами, якщо в моїй таблиці вже є записи.
Я отримав би "ПОМИЛКА: стовпець created_at
містить null
значення".
Для виправлення я використав:
def up
add_column :projects, :created_at, :datetime, default: nil, null: false
add_column :projects, :updated_at, :datetime, default: nil, null: false
end
Потім я використовував gem migra_data, щоб додати час для поточних проектів з міграції, таких як:
def data
Project.update_all created_at: Time.now
end
Тоді всі проекти, створені після цієї міграції, будуть правильно оновлені. Переконайтеся, що сервер також перезапущений, щоб Rails ActiveRecord
почав відслідковувати часові позначки на записі.
Тут дуже багато відповідей, але я також розміщу свої, тому що жоден з попередніх не працював для мене :)
Як зазначали деякі, #add_timestamps
на жаль, додається null: false
обмеження, яке спричинить невірність старих рядків, оскільки ці значення не заповнюються. Більшість відповідей тут передбачають, що ми встановимо якесь значення за замовчуванням ( Time.zone.now
), але я не хотів би цього робити, оскільки ці часові позначки за замовчуванням для старих даних не будуть правильними. Я не бачу значення в додаванні невірних даних до таблиці.
Тож моя міграція була просто:
class AddTimestampsToUser < ActiveRecord::Migration
def change_table
add_column :projects, :created_at, :datetime
add_column :projects, :updated_at, :datetime
end
end
Ні null: false
, ніяких інших обмежень немає. Старі рядки продовжуватимуть діяти created_at
як як NULL
, так і update_at
як NULL
(до деякого оновлення для рядка). Нові ряди з’являться created_at
та updated_at
заповнюються, як очікувалося.
Проблема з більшістю відповідей тут полягає в тому, що якщо за замовчуванням для Time.zone.now
всіх записів буде мати час виконання міграції як їх час за замовчуванням, що, мабуть, не те, що ви хочете. У рейках 5 ви можете замість цього використовувати now()
. Це встановить часові позначки для існуючих записів як час запуску міграції, так і час початку транзакції для здійснення знову вставлених записів.
class AddTimestampsToUsers < ActiveRecord::Migration
def change
add_timestamps :users, default: -> { 'now()' }, null: false
end
end
Використання Time.current
- це гарний стиль https://github.com/rubocop-hq/rails-style-guide#timenow
def change
change_table :users do |t|
t.timestamps default: Time.current
t.change_default :created_at, from: Time.current, to: nil
t.change_default :updated_at, from: Time.current, to: nil
end
end
або
def change
add_timestamps :users, default: Time.current
change_column_default :users, :created_at, from: Time.current, to: nil
change_column_default :users, :updated_at, from: Time.current, to: nil
end
Це просте додавання часової позначки в існуючу таблицю.
class AddTimeStampToCustomFieldMeatadata < ActiveRecord::Migration
def change
add_timestamps :custom_field_metadata
end
end
Це виглядає як чисте рішення в Rails 5.0.7 (виявив метод change_column_null):
def change
add_timestamps :candidate_offices, default: nil, null: true
change_column_null(:candidate_offices, :created_at, false, Time.zone.now)
change_column_null(:candidate_offices, :created_at, false, Time.zone.now)
end
Я на рейках 5.0 і жоден із цих варіантів не працював.
Єдине, що працювало, було використовувати тип, який буде: timetamp, а не: datetime
def change
add_column :users, :created_at, :timestamp
add_column :users, :updated_at, :timestamp
end
Я зіткнувся з тим же питанням на Rails 5, намагаючись використовувати
change_table :my_table do |t|
t.timestamps
end
Мені вдалося додати стовпчики часових позначок вручну за допомогою наступного:
change_table :my_table do |t|
t.datetime :created_at, null: false, default: DateTime.now
t.datetime :updated_at, null: false, default: DateTime.now
end