0

私は、yamler を Syck から Psych に移動し、最終的にプロジェクトを Ruby 2 にアップグレードできるようにするための移行を作成するのに忙しいです。

使用する予定の移行の結果が期待どおりの結果をもたらし、ダウンタイムなしで実行できることを確認するために、次の方法を作成しました。シリアル化を自動的に実行する Active レコードを回避するには、使用する必要がありました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から取得したもの

4

1 に答える 1

8

LIMITSQLとOFFSET句を使用して簡単に何かを構築できます。

def fetch_data(table_name, column_name)
  batch_size, offset = 1000, 0
  begin
    batch = ActiveRecord::Base.connection.select_all <<-SQL
      SELECT id, #{column_name}
      FROM #{table_name}
      WHERE #{column_name} LIKE '---%'
      LIMIT #{batch_size} 
      OFFSET #{offset}
    SQL
    batch.each do |row|
      yield row
    end
    offset += batch_size
  end until batch.empty?
end

を除いて、以前とほぼ同じように使用できます.each

fetch_data(table_name, column_name) do |row| ... end

チッ!

于 2016-01-14T19:31:52.073 に答える