У меня есть таблица в приложении Rails с сотнями тысяч записей, и у них есть только created_at
временная метка. Я добавляю возможность редактировать эти записи, поэтому хочу добавить updated_at
метку времени в таблицу. В моей миграции для добавления столбца я хочу обновить все строки, чтобы новые updated_at
соответствовали старым created_at
, поскольку это значение по умолчанию для вновь созданных строк в Rails. Я мог бы выполнить find(:all)
и перебрать записи, но это заняло бы часы из-за размера таблицы. Я действительно хочу:
UPDATE table_name SET updated_at = created_at;
Есть ли лучший способ сделать это при миграции Rails с использованием ActiveRecord, а не с помощью необработанного SQL?
Yourmodel.update_all 'update_at=created_at'
лучше, нет? Это тоже работает на прицеле.up
за которой следует символdown
» . Так что считайтеdef change
только вместо этого.change
метода еще не существовало, но в этом случае я все же предпочитаю использовать явныйup
иdown
более явный (если вы хотите контролировать, что онdown
должен делать).Вы можете использовать update_all, который работает очень похоже на необработанный SQL. Это все, что у вас есть.
Кстати, лично я не особо обращаю внимание на миграции. Иногда чистый SQL - действительно лучшее решение. Как правило, код миграции повторно не используется. Это разовое действие, поэтому я не беспокоюсь о чистоте кода.
источник
update_all
файла внутренней миграции :-) Вы также можете выполнить необработанный SQL внутри файла миграции. Однакоupdate_all
немного элегантнее. Оба будут работать одинаково.update_all
я не имею ни малейшего представления о том , как установить значение столбца , что другой, в соответствии с просьбой ОП. Пожалуйста, продемонстрируйте.Как писал грегдан, можно использовать
update_all
. Вы можете сделать что-то вроде этого:Model.where(...).update_all('updated_at = created_at')
Первая часть - это ваш типичный набор условий. В последней части рассказывается, как выполнять задания. Это приведет к
UPDATE
утверждению, по крайней мере, в Rails 4.источник
SET'posts'.'email' = 'options'
, параметры представляют собой буквальную строкуUser.update_all('updated_at = created_at')
SQL (0.4ms) UPDATE "users" SET updated_at = created_at
Вы можете напрямую запустить следующую команду на свой
rails console
ActiveRecord::Base.connection.execute("UPDATE TABLE_NAME SET COL2 = COL1")
Например: я хочу обновить sku моей таблицы элементов с помощью remote_id таблиц элементов. команда будет такой:
ActiveRecord::Base.connection.execute("UPDATE items SET sku = remote_id")
источник
Yourmodel
уже может быть удалена. Старайтесь избегать использования моделей в миграциях.Это общий способ решения, не требующий написания запроса, поскольку запросы подвержены риску.
class Demo < ActiveRecord::Migration def change add_column :events, :time_zone, :string Test.all.each do |p| p.update_attributes(time_zone: p.check.last.time_zone) end remove_column :sessions, :time_zone end end
источник
В качестве одноразовой операции я бы просто сделал это в
rails console
. Неужели это займет часы? Может быть, если будут миллионы записей…records = ModelName.all; records do |r|; r.update_attributes(:updated_at => r.created_at); r.save!; end;`
источник