2.0のscaffoldで上書きする

一度scaffoldを実行した後、同じモデルに何らかの変更をして再度scaffoldを実行したい場合、最初と同じ手順では実行できなかった...。

マイグレーションファイルの取り扱い

  • 2度目のscaffoldを実行したとき、同じモデルで既にマイグレーションファイルが存在すると、メッセージの最終行に以下のように表示され、何も更新されない。
Another migration is already named create_slips: db/migrate/001_create_slips.rb

2度目のscaffoldでファイルを上書きするためには...

ここで、Railsはどうやって同じモデルのマイグレーションだと理解するのか、という疑問が浮かぶ。

  • 試しにファイル名を001_create_slips.rb → 001_create_slips1.rbのように変更してみると...
    • 002_create_slips.rbが生成*1された!ファイル名を修正して利用するという方法もありだ。
    • 既にマイグレーションのバージョンNo.が進んでいる場合は、この方法が良いかもしれない。
マイグレーションファイル名を変更する時の注意

マイグレーションファイル名とその中身のマイグレーションクラス名は連動しているので、ファイル名を「001_create_slips1.rb」のように変更したら、クラス名も「CreateSlips1」のように変更する必要がある。この変更をしないとマイグレーションを実行した時にエラーが発生する。

rake aborted!
uninitialized constant CreateSlips1


scaffoldでマイグレーションファイルが生成されるようになったので、矛盾を防ぐためにこのような仕様になっていると思う。もし、マイグレーションファイルが上書きされてしまうと、データベースの状態とマイグレーションファイルに不整合が発生してしまい、後で困った状況になってしまうからだろう。

上書きの選択

  • scaffoldでファイルの上書きが発生する場合、以下のようなメッセージが表示される。
overwrite app/controllers/slips_controller.rb? (enter "h" for help) [Ynaqdh]
  • 改行、まはたhを指定すると、選択肢のペルプが表示される。
Y - yes, overwrite(上書きする)
n - no, do not overwrite(上書きしない)
a - all, overwrite this and all others(すべてのファイルで上書きする)
q - quit, abort(scaffold処理を中断する)
d - diff, show the differences between the old and the new(新旧の差分を表示する)
h - help, show this help(ヘルプ表示)
  • 初めて見るdオプションは素晴らしかった!既存ファイルと新規生成されるファイルのdiffを実行してくれる。(差分を表示する)
 --- /Users/zari/railsapp/test202/app/controllers/slips_controller.rb
 +++ /Users/zari/railsapp/test202/app/controllers/slips_controller.rb.26440.0
 @@ -4,6 +4,10 @@
    def index
      @slips = Slip.find(:all)
 
 +    respond_to do |format|
 +      format.html # index.html.erb
 +      format.xml  { render :xml => @slips }
 +    end
    end
 
   # GET /slips/1
 retrying
overwrite app/controllers/slips_controller.rb? (enter "h" for help) [Ynaqdh]
  • 変更内容を確認してから、上書きするか、しないかを選択すれば良いのだ。

ルートファイルの取り扱い

  • 正常にscaffoldが実行される度に、config/Routes.rbにmap.resources :slipsが追加されていく。油断していると、以下のような状態に...。
ActionController::Routing::Routes.draw do |map|
  map.resources :slips

  map.resources :slips

  map.resources :slips
...(中略)...
  • 重複する行は不要なので、削除しておいた。

*1:create_モデル名sというマイグレションファイルの存在をチェックしていると推測