Можно ли использовать Rails Migrations для преобразования данных? - PullRequest
32 голосов
/ 12 мая 2009

Я пытаюсь преобразовать столбец в моем приложении Rails, ради аргументов, давайте представим, что я пытаюсь изменить столбец age в моей таблице users на строковое представление, а не на int.

В моей миграции у меня есть это;

def.self up
    add_column :users, :age_text, :string

    users = User.find(:all)

    users.each do |u|
       u.age_text = convert_to_text(u.age)
       u.save
    end
end

def self.convert_to_text(number)
   #code here to convert 1 to 'one' etc
end

Но, похоже, это не работает, возможно ли то, что я пытаюсь здесь сделать, даже с миграциями?

Ответы [ 4 ]

58 голосов
/ 12 мая 2009

То, что вы пытаетесь сделать, возможно, и я бы сказал, что нужно сделать.

Однако вам необходимо перезагрузить информацию о столбцах для классов моделей, которые вы обновляете в процессе миграции, чтобы Rails знал о новых столбцах. Попробуйте это:

def.self up
    add_column :users, :age_text, :string

    User.reset_column_information 

    users = User.find(:all)

    users.each do |u|
       u.age_text = convert_to_text(u.age)
       u.save
    end
end

В отдельном примечании, пожалуйста, обратите внимание, что если ваша таблица велика, обновление одного за другим займет много времени .. Будьте осторожны с этим.

39 голосов
/ 14 мая 2009

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

ОБЩАЯ манипуляция данными в миграциях - ПЛОХАЯ идея. Миграции с прямым доступом к модели могут застрять при изменении логики модели.

Представьте, что во второй миграции вы добавили новый столбец. Вы хотите заполнить этот столбец новыми данными.

Допустим, через несколько недель вы добавите в модель новую валидацию - валидацию, которая работает с полем, которого еще нет во второй миграции. если бы вы когда-нибудь построили базу данных из миграции 0, у вас были бы некоторые проблемы.

Я настоятельно рекомендую использовать миграции для изменения столбцов и другие средства для управления данными базы данных, особенно при переходе в рабочую среду.

4 голосов
/ 22 декабря 2013

Вот пример миграции, которую я запустил для преобразования данных. Вы можете легко преобразовать его, чтобы использовать целые числа вместо строк. Выполнение преобразования в SQL выполняется намного быстрее, чем загрузка каждой строки в Rails.

class ConvertCommentTextToText < ActiveRecord::Migration
  def up
    add_column :comments, :text_tmp, :text
    # copy text column
    execute <<-SQL
      update comments set text_tmp = text
    SQL
    remove_column :comments, :text
    rename_column :comments, :text_tmp, :text
  end

  def down
    add_column :comments, :text_tmp, :string
    # copy text column
    execute <<-SQL
      update comments set text_tmp = text
    SQL
    remove_column :comments, :text
    rename_column :comments, :text_tmp, :text
  end

end

И чтобы проверить это:

rake db:migrate
rake db:rollback
rake db:migrate
0 голосов
/ 20 мая 2009

Я бы сказал, что если вы можете «отменить» импортированные данные при откате версии миграции, то целесообразно включить импорт в миграцию.

Например, у меня есть миграция, которая устанавливает много таблиц поиска и других метаданных. Данные для этих таблиц заполняются на этом этапе. По мере изменения данных для этих таблиц поиска я создаю новые YAML-файлы, хранящие метаданные, и загружаю эти файлы в последующих миграциях (и отменяю эти YAMLS, перезагружая предыдущий YAML-файл при выходе из версии миграции). Это довольно чисто. У меня есть файлы (в разных четко определенных папках в моем случае) с этими файлами:

002_setup_meta_data.rb
002_meta_data.yaml


007_change_meta_data.rb
007_meta_data.yaml

Если вы импортируете «производственные» данные из другой системы в транзакционные (нестатические) таблицы, то я бы сказал, что использование миграций не подходит. Тогда я бы последовал совету Брайана Хогана об использовании рейковых заданий.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...