Я занят написанием миграции, которая позволит нам перенести наш ямлер из Syck в Psych и, наконец, обновить наш проект до рубина 2. Эта миграция будет серьезно ресурсоемкой хотя я должен буду использовать chunking.Вычисление при использовании ActiveRecord :: Base.connection.execute
Я написал следующий метод, чтобы подтвердить, что результат переноса, который я планирую использовать, дает ожидаемый результат и может быть выполнен без простоя. Для того, чтобы избежать активной записи выполнения сериализации автоматически мне нужно использовать ActiveRecord::Base.connection.execute
Моего метода, который описывает преобразование следующего
def show_summary(table, column_name)
a = ActiveRecord::Base.connection.execute <<-SQL
SELECT id, #{column_name} FROM #{table}
SQL
all_rows = a.to_a; ""
problem_rows = all_rows.select do |row|
original_string = Syck.dump(Syck.load(row[1]))
orginal_object = Syck.load(original_string)
new_string = Psych.dump(orginal_object)
new_object = Syck.load(new_string)
Syck.dump(new_object) != original_string rescue true
end
problem_rows.map do |row|
old_string = Syck.dump(Syck.load(row[1]))
new_string = Psych.dump(Syck.load(old_string)) rescue "Parse failure"
roundtrip_string = begin
Syck.dump(Syck.load(new_string))
rescue => e
e.message
end
new_row = {}
new_row[:id] = row[0]
new_row[:original_encoding] = old_string
new_row[:new_encoding] = roundtrip_string
new_row
end
end
Как вы можете использовать пакетный при использовании ActiveRecord::Base.connection.execute
?
Для полноты моя функция обновления заключается в следующем
# Migrate the given serialized YAML column from Syck to Psych
# (if any).
def migrate_to_psych(table, column)
table_name = ActiveRecord::Base.connection.quote_table_name(table)
column_name = ActiveRecord::Base.connection.quote_column_name(column)
fetch_data(table_name, column_name).each do |row|
transformed = ::Psych.dump(convert(Syck.load(row[column])))
ActiveRecord::Base.connection.execute <<-SQL
UPDATE #{table_name}
SET #{column_name} = #{ActiveRecord::Base.connection.quote(transformed)}
WHERE id = #{row['id']};
SQL
end
end
def fetch_data(table_name, column_name)
ActiveRecord::Base.connection.select_all <<-SQL
SELECT id, #{column_name}
FROM #{table_name}
WHERE #{column_name} LIKE '---%'
SQL
end
который я получил от http://fossies.org/linux/openproject/db/migrate/migration_utils/legacy_yamler.rb
Кстати, я всегда стараюсь избегать использования моделей ActiveRecord при миграции. Просто потому, что исходный код модели может быть изменен, но моя миграция еще может быть использована через год, чтобы настроить тестовые базы данных. – Raffael
Спасибо за ваш ответ! Это действительно полезно! У меня была боль в начале этого года в моем проекте с изменением моделей, а затем с миграциями данных, в которых произошла авария с активной записью. –
Это работает хорошо, только одна заметка [не использовать begin; конец до синтаксиса] (https://stackoverflow.com/questions/136793/is-there-a-do-while-loop-in-ruby) – fguillen