it-swarm.com.ru

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

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

UPDATE table_name SET updated_at = created_at;

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

64
jrdioko

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

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> ...")
114
nathanvda

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

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

20
Greg Dan

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

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

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

10
Martin Streicher

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

  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
0
Wilson Varghese