【Rails Girls参加者向け】scaffold作成時にカラム名（属性名）を打ち間違えた場合の修正手順

## はじめに

この記事では[Rails Girls アプリ・チュートリアル](http://railsgirls.jp/app)でscaffold作成時にカラム名（属性名）を打ち間違えた場合の修正手順を説明します。

なお、間違いに気づいたタイミングによって対処法が異なるので、自分がどのタイミングに該当しているか十分注意してください。
コーチが横にいる場合はコーチと一緒に作業を進めましょう。

## この記事で想定するミスについて

この記事では間違えて`name`を`neme`と入力してしまった場合を想定します。

```
# うっかりnameではなく、nemeと入力してしまった！
rails generate scaffold idea neme:string description:text picture:string
```

画面上でも"Neme"になってしまっている↓

![Screen Shot 2018-06-19 at 9.22.54.png](https://qiita-image-store.s3.amazonaws.com/0/7465/c632ff73-e90d-e698-31bc-35c2cd71a428.png)

## 対象となる実行環境

この記事は以下の環境で動作確認しています。

- Rails 5.2.0
- Ruby 2.5.1
- macOS 10.13.5

## ケース0: いきなりファイルを変更してはいけない

作業中に入力ミスに気づいたからといって「しまった、直さなきゃ！」と、いきなりファイルを修正してはいけません。

プログラムは非常に繊細です。
あわててファイルを修正してしまうと、他のファイルやデータベースとの間で整合性がとれなくなり、システムエラーが発生します。

初心者のうちはエラーが発生すると、余計に混乱するもとになってしまうので、すぐにコードを直そうとせず、以下の手順を一通り読んでから修正作業に移ってください。

## ケース1: scaffold作成直後に気づいた場合（db:migrateをまだ実行していない場合）

以下のコマンドをターミナルから実行すると、直前に作成したscaffold関係のファイルをすべて削除できます。

```
rails destroy scaffold idea
```

このコマンドを実行すると、以下のような表示が出力されます。

```
Running via Spring preloader in process 16335
      invoke  active_record
      remove    db/migrate/20180619000740_create_ideas.rb
      remove    app/models/idea.rb
      invoke    test_unit
      remove      test/models/idea_test.rb
      remove      test/fixtures/ideas.yml
      invoke  resource_route
       route    resources :ideas
      invoke  scaffold_controller
      remove    app/controllers/ideas_controller.rb
      invoke    erb
      remove      app/views/ideas
      remove      app/views/ideas/index.html.erb
      remove      app/views/ideas/edit.html.erb
      remove      app/views/ideas/show.html.erb
      remove      app/views/ideas/new.html.erb
      remove      app/views/ideas/_form.html.erb
      invoke    test_unit
      remove      test/controllers/ideas_controller_test.rb
      remove      test/system/ideas_test.rb
      invoke    helper
      remove      app/helpers/ideas_helper.rb
      invoke      test_unit
      invoke    jbuilder
      remove      app/views/ideas
      remove      app/views/ideas/index.json.jbuilder
      remove      app/views/ideas/show.json.jbuilder
      remove      app/views/ideas/_idea.json.jbuilder
      invoke  assets
      invoke    coffee
      remove      app/assets/javascripts/ideas.coffee
      invoke    scss
      remove      app/assets/stylesheets/ideas.scss
      invoke  scss
```

ファイルが削除できたら、再度scaffoldを作成します。
（今度は入力ミスしないように！）

```
rails generate scaffold idea name:string description:text picture:string
```

あとは、`rails db:migrate`以降の作業を通常通り進めてください。

## ケース2: 「3. デザインする」の作業途中で気づいた場合

厳密に言うと、`rails db:migrate`は実行したが、`app/models/idea.rb`や`app/views/ideas/_form.html.erb`はまだ変更していない場合がこのケースに該当します。

まず、ターミナルから以下のコマンドを実行して、データベースに加えた変更を取り消します。

```
rails db:rollback
```

このコマンドを実行すると、以下のような表示が出力されます。

```
== 20180619002035 CreateIdeas: reverting ======================================
-- drop_table(:ideas)
   -> 0.0008s
== 20180619002035 CreateIdeas: reverted (0.0041s) =============================
```

それからscaffoldの削除を実行します（実行時の出力例は省略）。

```
rails destroy scaffold idea
```

`rails destroy scaffold`では作成されたファイル（ソースコード）を削除するだけで、データベースに加えた変更（テーブルの作成等）は取り消してくれないため、`rails db:rollback`と`rails destroy scaffold idea`を別々に実行する必要があります。

また、`rails db:rollback`の実行にはマイグレーションファイル（`db/migrate/20180619000740_create_ideas.rb`等）が必要です。
そのため、必ず、`rails db:rollback` → `rails destroy scaffold idea`の順でコマンドを実行する必要があります（先に`rails destroy scaffold idea`を実行すると、migrationファイルが削除されてしまう）。

続いてターミナルからscaffoldの作成とマイグレーションの実行を行います。

```
rails generate scaffold idea name:string description:text picture:string

rails db:migrate
```

これで修正が完了したはずです。
途中まで進めていた作業を再開してください。

### チーム開発している場合の注意点
Rails Girlsの手順に従って開発しているときはこれで問題ありませんが、もしこれがチーム開発していて、コードをGitHubで管理している場合は、後述する「ケース3」の対応を取る方が望ましいです。

なぜその方が良いのかは以下の記事にまとめてあります（ただし、プログラミング初心者さんにはちょっと難しいかも）。

[GitHubにpushしたmigrationファイルは安易に修正してはいけません \- Qiita](https://qiita.com/jnchito/items/3525fd22973477b88411)

## ケース3: 「4. 写真アップロード機能を追加する」以降で気づいた場合

すでに`app/models/idea.rb`や`app/views/ideas/_form.html.erb`に変更を加えてしまった場合がこのケースに該当します。

この場合は以下のような大まかに言うと、以下のような手順になります。

1. カラムの名前を変更するマイグレーションを実行する
2. ソースコード中の誤った名前を正しい名前に全部修正していく
3. 実際に画面を動かして正常に動くことを確認する

それぞれ以下で詳しく説明します。

### 1. カラムの名前を変更するマイグレーションを実行する

ターミナルから以下のコマンドを実行します。

```
rails generate migration RenameNemeToNameInIdeas
```

`rails generate migration (マイグレーション名)`で、新しいマイグレーションファイルを作成できます。
`RenameNemeToNameInIdeas`の部分は自由に命名できます。
ここでは「IdeasのNemeをNameにリネームする」という意味で、"rename neme to name in ideas"という名前を付けました。

上のコマンドを実行すると、次のような出力が表示されます。

```
Running via Spring preloader in process 20053
      invoke  active_record
      create    db/migrate/20180619005208_rename_neme_to_name_in_ideas.rb
```

テキストエディタで`db/migrate/何らかの数字_rename_neme_to_name_in_ideas.rb`を開いて、次のように入力します。

```ruby:db/migrate/何らかの数字_rename_neme_to_name_in_ideas.rb
class RenameNemeToNameInIdeas < ActiveRecord::Migration[5.2]
  def change
    rename_column :ideas, :neme, :name
  end
end
```

`db/migrate/`以下に作成されたファイルをマイグレーションファイルと言い、データベースに何か変更を加える際に利用します。

ここでは`rename_column :ideas, :neme, :name`というコードを書きました。
これは「`ideas`テーブルの`neme`というカラムを`name`という名前に変更（rename）しろ」という意味です。

ファイルを保存したら、ターミナルからマイグレーションファイルの内容を実行します。

```
rails db:migrate
```

実行すると以下のような出力が表示されます。

```
== 20180619005208 RenameNemeToNameInIdeas: migrating ==========================
-- rename_column(:ideas, :neme, :name)
   -> 0.0045s
== 20180619005208 RenameNemeToNameInIdeas: migrated (0.0046s) =================
```

これで、データベース上のカラム名を修正できました。

### 2. ソースコード中の誤った名前を正しい名前に全部修正していく
続いて、ソースコード中の誤った名前を正しい名前に全部修正していく必要があります。
この記事では"neme"を"name"に変更していきます。
また、大文字と小文字は区別する必要があるので、"Neme"は"Name"に変更する必要があります。

ターミナルから次のようなコマンドを実行すると、ソースコード中の"neme"を検索することができます。

```
git add .

git grep neme
```

以下はその出力例です。
「ファイルパス（ファイルがある場所）: 検索したコードが存在する箇所」の形式で、検索結果が表示されます。

```
app/controllers/ideas_controller.rb:      params.require(:idea).permit(:neme, :description, :picture)
app/views/ideas/_form.html.erb:    <%= form.label :neme %>
app/views/ideas/_form.html.erb:    <%= form.text_field :neme %>
app/views/ideas/_idea.json.jbuilder:json.extract! idea, :id, :neme, :description, :picture, :created_at, :updated_at
app/views/ideas/index.html.erb:        <td><%= idea.neme %></td>
app/views/ideas/show.html.erb:  <%= @idea.neme %>
db/migrate/20180619004342_create_ideas.rb:      t.string :neme
db/migrate/20180619005208_rename_neme_to_name_in_ideas.rb:    rename_column :ideas, :neme, :name
test/controllers/ideas_controller_test.rb:      post ideas_url, params: { idea: { description: @idea.description, neme: @idea.neme, picture: @idea.picture } }
test/controllers/ideas_controller_test.rb:    patch idea_url(@idea), params: { idea: { description: @idea.description, neme: @idea.neme, picture: @idea.picture } }
test/fixtures/ideas.yml:  neme: MyString
test/fixtures/ideas.yml:  neme: MyString
test/system/ideas_test.rb:    fill_in "Neme", with: @idea.neme
test/system/ideas_test.rb:    fill_in "Neme", with: @idea.neme
```

検索結果を閉じるときは`q`を入力します。

同じように`git grep Neme`と入力して、大文字の"Neme"も検索してみましょう。

```
app/views/ideas/index.html.erb:      <th>Neme</th>
app/views/ideas/show.html.erb:  <strong>Neme:</strong>
db/migrate/20180619005208_rename_neme_to_name_in_ideas.rb:class RenameNemeToNameInIdeas < ActiveRecord::Migration[5.2]
test/system/ideas_test.rb:    fill_in "Neme", with: @idea.neme
test/system/ideas_test.rb:    fill_in "Neme", with: @idea.neme
```

あとは、対象のファイルを開いて"neme"や"Neme"を一つずつ修正していけばOK・・・なのですが、一点注意事項があります。
マイグレーションファイルだけは特殊なファイルなので、修正しないでください。
上の実行例でいうと、以下の2つのファイルは今回の対象外になります。

- `db/migrate/20180619004342_create_ideas.rb`
- `db/migrate/20180619005208_rename_neme_to_name_in_ideas.rb`

その点に注意した上で、ソースコードを順次修正していってください。


### 3. 実際に画面を動かして正常に動くことを確認する

このケースではたくさんのファイルを一度に変更したので、もしかすると予期しない部分でエラーが発生するかもしれません。
一通り画面を操作して、アプリケーションが正常に動作することを確認しましょう。

エラーが出た場合は、じっくりとエラーの内容を確認しながら、原因を突き止めて修正してください。
（ただし、エラーの修正は初心者のうちは難しいかもしれないので、できればメンターと一緒に進めてください。）

## まとめ

というわけで、この記事ではRails Girlsの参加者向けに、scaffold作成時にカラム名（属性名）を打ち間違えた場合の修正手順を説明しました。

うっかり入力を間違えてしまった場合は、この記事を参考にしながら、落ち着いて対処してください。