1

このスニペットを含む友人によるレガシーアプリのかなり古い移行があります:

class MakeChangesToProductionDbToMatchWhatItShouldBe < ActiveRecord::Migration
  def self.up

# For some reason ActiveRecord::Base.connection.tables.sort().each blows up
    ['adjustments',
    'accounts',
     ...## more rows of classes here ###...
    'product_types'].each do |table|
      t = table.singularize.camelize.constantize.new
      if t.attributes.include?('created_at')
        change_column( table.to_sym, :created_at, :datetime,  :null => false ) rescue puts      "#{table} doesnt have created_at"
      end
      if t.attributes.include?('updated_at')
        change_column( table.to_sym, :updated_at, :datetime,  :null => false ) rescue puts "#{table} doesnt have updated_at"
      end
    end

この古い移行は、この長いリストに記載されている 2 つのテーブルを削除するために私が書いた新しい移行と競合しています。これにより、rake db:migrate でデプロイがエラーになります。

この移行に対処して db:migrate を再び機能させるために書く正しい種類の移行または停止アクションは何ですか?

4

1 に答える 1

2

役立つベスト プラクティスがいくつかありますが、結局のところ、移行を実行する際にコードベースをステップ実行せずに任意の時点からデータベースを常にアップグレードする良い方法はありません (そういえば、なぜそうでないのかこれを行うには、すでに rake タスクが必要ですか?)。

  1. 作業中のモデルの移行名前空間のコピーを常に含めます。以下の例。
  2. データベースをゼロから構築する場合は、移行を実行しないdb:schema:loadでください。データベースの最後のスナップショットを再作成する移行を使用してください。
  3. 移行にばかげた、攻撃性を煽るMakeChangesToProductionDbToMatchWhatItShouldBe.
  4. 移行を作成するときは、移行が実行される環境について想定しないでください。これには、テーブル名、データベース ドライバー、環境変数などの指定が含まれます。
  5. ダウンアクションが実行可能な場合はいつでも、アクションを書き出すときにアクションを書き留めます。一連の変換が頭の中で新鮮な場合、通常ははるかに簡単です (特に難解な移行または複雑な移行の場合)。

この特定のケースについては、「移行の破産」を宣言すること、つまり既存の移行の一部またはすべてを消去する (またはリファクタリングして新しい移行に統合する) ことで、望ましいデータベース状態を実現することについて議論する必要があります。これを行うと、下位互換性がなくなるため、軽視することはできませんが、適切な動きである場合があります。

于 2013-02-08T01:17:37.880 に答える