【rails】投稿機能の項目追加

# やること
railsアプリケーションで投稿機能の投稿フォームの項目を追加してみた！

# 現状こんな感じ
```html:new.html.erb
<div class="post-container">
    <%= form_for @post do |f| %>
        <%= f.label :body %>
        <%= f.text_field :body, size:140, required:true %>
        <%= f.submit "送信" %>
    <% end %>
    <%= link_to "投稿一覧", posts_path %>
</div>
```
`required:true`は必須回答という意味です！
```ruby:posts_controller.rb
class PostsController < ApplicationController

    # 省略

    def new
        @post = Post.new
    end
    def create
        post = Post.new(post_params)
        if post.save
            redirect_to :action => "index"
        else
            redirect_to :action => "new"
        end
    end

    # 省略
    
    private
    def post_params
        params.require(:post).permit(:body)
    end
end
```
```ruby:routes.rb
Rails.application.routes.draw do

  # 省略

  resources :posts
end
```
# 実際に追加していきましょう！！
### 1. カラムの追加
2パターン紹介します！！（**パターン2**がおすすめです！）
#### パターン1
migrationファイルの作成
```terminal:ターミナル
rails g migration Add<カラム名>ToPosts <カラム名>:<データ型>
```
具体的にはこんな感じ↓
```terminal:ターミナル
rails g migration AddTitleToPosts title:string
```
カラム名は自分で勝手に決めて大丈夫です！
**ちょっとだけ注意:pushpin:**
避けるべきカラム名というものがあります！
|禁止カラム名|用途|
|---|---|
|id|主キーとして使われるカラム|
|(テーブル名の単数形)_id|リレーションを表現するために使われるカラム|
|created_at|レコードの作成日時が自動更新されるカラム|
|updated_at|レコードの更新日時が自動更新されるカラム|
|type|STI(Single Table Inheritance) を利用する場合に使うカラム|
|xxx_type|ポリモーフィック関連を利用する際のカラム|
|lock_version|楽観的ロック(Optimistic Locking)を実現するためのカラム|

これらは予約語といってあらかじめそのカラム名とその役割が決められているもののことです！
なので、決められた以外の役割では使用できません！！

詳しくは[Railsガイド](https://railsguides.jp/active_record_migrations.html#%E3%82%AB%E3%83%A9%E3%83%A0%E5%90%8D%E3%82%92%E5%A4%89%E6%9B%B4%E3%81%99%E3%82%8B)をみてください！！（日本語です！！）

データ型はたくさん種類があります！！
よく使うものだけ紹介しときます！！
|データ型|意味|
|---|---|
|string|文字列（255文字以下）|
|text|文字列（4,294,967,296文字以下）|
|integer|整数|
|float|浮動小数|
|datetime|日付と時刻|
|boolean|true / false|

詳しくは[Railsガイド](https://railsguides.jp/active_record_migrations.html)をみてください！！

maigrationファイルの追加が成功していたら`db/migrate`フォルダに下記のようなファイルが追加されています！
(数字のところは日付です！)
```ruby:db/migrate/20220524061805_add_title_to_posts.rb
class AddTitleToPosts < ActiveRecord::Migration[6.1]
  def change
    add_column :posts, :title, :string
  end
end
```
追加されていたら以下を実行していきましょう！！
```terminal:ターミナル
rails db:migrate
```
ここまででカラムの追加は以上ですが、最後ちょっとだけ確認しときましょう！
```terminal:ターミナル
rails db:migrate:status
```
![スクリーンショット 2022-05-24 15.36.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2586059/a88baab0-f12a-c092-8101-cbe0d299a87e.png)

何個ファイルが出てきたかは関係ありません！
見るところは、先ほど作ったファイルがあるかどうかとstatusが全てupになっているかです！

うまくいかない点として良くあるものを２つ紹介しておきます！
一番下のファイルのみがdownの時↓
* もうすでに存在するカラム名を追加しようとしてる！
    * `db/schema.rb`で今どんなカラムがあるか確認しましょう！
* マイグレーションファイルの中身を書き換えちゃってるor追加するためのコードが間違っている
    * 追加した`20220524061805_add_title_to_posts.rb`ファイルを削除して、migrationファイルの追加からやり直しましょう！！

もう一個確認項目！ちょっと書いちゃいましたが、`db/schema.rb`ファイルにカラムが追加できてるか確認しましょう！！
```ruby:db/schema.rb

# 省略

  create_table "posts", force: :cascade do |t|
    t.string "title" # 追加されてる！！
    t.string "body"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
  end

# 省略

```

これでパターン1終了です！

#### パターン2
パターン2では既にあるmaigrationファイルを編集して、追加していきます！！
既に`db/migrate`フォルダの中には、`20220426094637_create_posts.rb`という、テーブルを作成するためのmigrationファイルが存在します！
なので、これを編集することで、テーブルを作成する段階で一緒にカラムも作っちゃおう！って感じのノリです！

それではやっていきます！！

まずは今あるmigrationファイルを確認しましょう
vscodeはこんな感じでした！
![スクリーンショット 2022-05-24 19.41.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2586059/9043ca0f-8880-f051-8598-8c199e1ec12b.png)

`2022~~~_create_<テーブル名>.rb`みたいなファイルでテーブルを作成します！
今回は`20220426094637_create_posts.rb`というファイルでpostsテーブルを作成しているので、ここを編集することになります！！

**ここで注意ポイント:pushpin:**
パターン1で少し出てきたup/downがmigrationファイルを編集する上で重要です！
まずmigrationファイルにはファイルごとにstatusがあります（up/downのこと！）
そのstatusを確認できるのが、
```terminal:ターミナル
rails db:migrate:status
```
これです！
実行したらこんな感じです！
![スクリーンショット 2022-05-24 19.51.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2586059/e8fdb44d-5f88-a613-0b7a-1dbb90522a70.png)

サイトを使うときはmigrationファイルは全てupである必要がありますが、**upの時にmigrationファイルの編集は禁止です！**

なので、ここからやっていくことは
1. テーブルを作っているmigrationファイルのstatusを**down**にする
1. テーブルを作っているmigrationファイルの中にカラムを追加する
1. テーブルを作っているmigrationファイルのstatusを**up**にする

っていう感じです！！
まずはdownにしましょう！
```terminal:ターミナル
rails db:rollback
```
これで一番新しく作ったmigrationファイルが１つ分downになります！
(ミスをしないポイントはこまめに`rails db:migrate:status`でstatusを確認することです！)
`rails db:rollback`を1回実行するとこんな感じです！
![スクリーンショット 2022-05-24 20.03.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2586059/188161e8-12be-aaab-a66e-3dc9ab15d651.png)

一番下のmigrationファイルがdownになりました！
同じようにもう一回`rails db:rollback`を実行するとさらにもう一個migrationファイルがdownになりますが、何回も同じコードを打つのはめんどくさいので一気にやっちゃいましょー！！
```terminal:ターミナル
rails db:rollback STEP=<数字>
```
書いた数字の数だけmigrationファイルをdownにできます！例えば
```terminal:ターミナル
rails db:rollback STEP=5
```
![スクリーンショット 2022-05-24 20.09.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2586059/1af3d8f7-14ff-b9c4-a730-8d883ed4c538.png)

今回はこんな感じでpostsテーブルを作成するmigrationファイル（`20220426094637_create_posts.rb`）がdownになったのでmigrationファイルの編集（追記）をしていきましょう！！(今回の場合だと5個分downにしなくても2個分で大丈夫ですね！)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2586059/fb2fafa7-eca2-a06f-08bc-362f6ee79196.png)

現状こんな感じでした
```ruby:db/migrate/20220426094637_create_posts.rb
class CreatePosts < ActiveRecord::Migration[6.1]
  def change
    create_table :posts do |t|
      t.string :body

      t.timestamps
    end
  end
end
```
ここの、`t.string :body`と`t.timestamps`がpostsテーブルのカラム名ですね！！
追記していきます！！
```ruby:db/migrate/20220426094637_create_posts.rb
class CreatePosts < ActiveRecord::Migration[6.1]
  def change
    create_table :posts do |t|
      t.string :body
      t.string :title # 追記

      t.timestamps
    end
  end
end
```
（今回は1個しか追加しませんが、何個でも追記できます！）

ここまでで編集が終わりなので、次はmigrationファイルをupにしていきます！！
```terminal:ターミナル
rails db:migrate
```
downにするときは数字を指定したり、１つずつしかできなかったりしましたが、upの時は全部一気にしてくれます！！
一応upにできてるか確認してみます！！
```terminal:ターミナル
rails db:migrate:status
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2586059/3cf59cae-3b1a-82e1-afc3-d136cbc5ccab.png)
これでちゃんと追加されています
```ruby:db/schema.rb

# 省略

  create_table "posts", force: :cascade do |t|
    t.string "title" # 追加されてる！！
    t.string "body"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
  end

# 省略

```
これでパターン2も終了です！！
パターン2をお勧めしている理由は２つあって、１つ目が、一気に何個もカラムを追加したい時に、migrationファイル内に羅列していきばいいだけなのでちょー簡単！！！２つ目がmigrationファイルが増えないことです！それだけか。。と思うかもしれないですが、ファイルの見やすさはエラーを予防できます！！パターン1のように１つのテーブル内のカラムが複数のmigrationファイルにまたがって記述されてしまうとミスの原因になります！（`db/schema.rb`で見れるやんとか言わないでねww）

### 2. viewページでフォームの追加
カラムが追加できたら次にviewページにフォームを追加していきます！
```html:new.html.erb
<div class="post-container">
    <%= form_for @post do |f| %>
        <!-- 追記 -->
        <%= f.label :title %> 
        <%= f.text_field :title, size:140, required:true %>
        <!-- 追記終わり -->
        <%= f.label :body %>
        <%= f.text_field :body, size:140, required:true %>
        <%= f.submit "送信" %>
    <% end %>
    <%= link_to "投稿一覧", posts_path %>
</div>
```
今回は`text_field`を使いましたが、フォームにはたくさんの種類があるので個人的によく使うものを紹介します！！
|メソッド|機能|
|---|---|
|text_field|テキストボックス|
|text_area|テキストエリア|
|label|ラベル|
|number_field|整数選択|
|date_field|日付ボックス|
|datetime_field|日付時刻ボックス|
|select|選択ボックス|
|file_field|ファイル選択ボックス|
|hidden_field|隠しボックス|
|check_box|チェックボックス|
|radio_button|ラジオぼたん|
|submit|送信ボタン|

[もっとあるよー](https://railsguides.jp/form_helpers.html)

### 3. ストロングパラメータ
最後にコントローラに追記していきます！！
```ruby:posts_controller.rb
class PostsController < ApplicationController

    # 省略

    def new
        @post = Post.new
    end
    def create
        post = Post.new(post_params)
        if post.save
            redirect_to :action => "index"
        else
            redirect_to :action => "new"
        end
    end

    # 省略
    
    private
    def post_params
        params.require(:post).permit(:body, :title) # 追記
    end
end
```
追記部分はここです！！
```ruby
params.require(:post).permit(:body, :title) # 追記
```
ここでは投稿する時に使うカラム名を全て記述していきましょう！！
注意点としては、やったことない人もいるかもしれませんが、チェックボックスなどを使った時に、こんな感じになります！！
```ruby
params.require(:post).permit(:title, name: [], check: [])
```
このような`[]`があるときは後ろに寄せときましょう！
下のような書き方はダメです！！
```ruby
params.require(:post).permit(name: [], :title, weight: [])
```

# 終わり
ここまで読んでいただきありがとうございましたー
ばあああいばい