Подтвердить что ты не робот

Обновить один столбец для значения другого в миграции Rails

У меня есть таблица в приложении Rails с сотнями тысяч записей, и у них есть только метка created_at. Я добавляю возможность редактировать эти записи, поэтому я хочу добавить временную метку updated_at к таблице. В моей миграции для добавления столбца я хочу обновить все строки, чтобы новый updated_at соответствовал старому created_at, поскольку это значение по умолчанию для вновь созданных строк в Rails. Я мог бы сделать find(:all) и перебирать записи, но это займет несколько часов из-за размера таблицы. Я действительно хочу:

UPDATE table_name SET updated_at = created_at;

Есть ли лучший способ сделать это в миграции Rails, используя ActiveRecord, а не выполнять необработанный SQL?

4b9b3361

Ответ 1

Я бы создал миграцию

rails g migration set_updated_at_values

и внутри его напишите что-нибудь вроде:

class SetUpdatedAt < ActiveRecord::Migration
  def self.up
    Yourmodel.update_all("updated_at=created_at")
  end

  def self.down
  end
end

Таким образом вы достигаете двух вещей

  • это повторяемый процесс, при каждом возможном развертывании (при необходимости) он выполняется
  • Это эффективно. Я не могу думать о более рубическом решении (это так же эффективно).

Примечание. Вы также можете запустить raw sql внутри миграции, если запрос становится слишком сложным для записи с использованием activerecord. Просто напишите следующее:

Yourmodel.connection.execute("update your_models set ... <complicated query> ...")

Ответ 2

Вы можете использовать update_all, который очень похож на исходный SQL. Это все варианты, которые у вас есть.

Я лично не обращаю внимания на миграцию. Иногда raw SQL - действительно лучшее решение. Обычно код миграции не используется повторно. Это однократное действие, поэтому я не беспокоюсь о чистоте кода.

Ответ 3

Как писал gregdan, вы можете использовать update_all. Вы можете сделать что-то вроде этого:

Model.where(...).update_all('updated_at = created_at')

Первая часть - ваш типичный набор условий. В последней части говорится, как выполнять задания. Это приведет к выражению UPDATE, по крайней мере, в Rails 4.

Ответ 4

Это общий способ решения без необходимости написания запроса, поскольку запросы подвергаются риску.

  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

Ответ 5

Вы можете напрямую запустить следующую команду на своей 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")

Ответ 6

Как однократная операция, я просто сделаю это в rails console. Это займет несколько часов? Может быть, если есть миллионы записей...

records = ModelName.all; records do |r|; r.update_attributes(:updated_at => r.created_at); r.save!; end;`