Railsアプリで新規投稿機能を実装する

#一覧画面に新規登録リンクを追加する
一覧画面(index.html.slim)に新規投稿画面へのリンクを設置します。
Bootstrap用にcssクラスを与えると、リンクをボタンのような外見にしてくれます。

```ruby:index.html.slim
h1 タスク一覧

= link_to '新規登録', new_posts_patch, class: btn btn-primary
```

Slimテンプレートでは、＝で始まる行はRubyコードの実行と出力をします。
link_toメソッドは、a要素を出力するメソッドです。
new_task_pathはURLヘルパーメソッドです。"/posts/new"というURL文字列を得られます。

#モデルの翻訳情報を追加する
投稿フォームを作る前に、下準備としてPostモデルの翻訳情報をconfig/locales/ja.ymlに追加。

```config/locales/ja.yml
ja:
  activerecord:
    errors:
      messages:
        record_invalid: 'バリデーションに失敗しました: %{errors}'
        restrict_dependent_destroy:
          has_one: "%{record}が存在しているので削除できません"
          has_many: "%{record}が存在しているので削除できません"
    models:
      post:投稿
    attributes:
      post:
      id: ID
      content: 投稿内容
      created_at: 登録日時
      updated_at: 更新日時
```

#新規登録画面用のアクションの実装
app/controllers/posts_controller.rbのnewアクションで、新規投稿画面の表示に必要な準備を行うようにします。
新しいPostオブジェクトを生成して、インスタンス変数@postに代入します。

```ruby:app/config/posts_controller.rb
  def new
    @post = Post.new
  end
```
アクションからビューに受け流しをしたいデータをインスタンス変数に入れることが、アクションの役割の一つです。

#新規投稿画面のプレビューを実装する。
newアクションに対応するファイルはapp/views/posts/new.html.slimです。
@postを利用し、form_withメソッドによって投稿フォームを表示します。
投稿を断念して一覧へできるように、一覧へのリンクも追加しています。

```ruby:app/views/posts/new.html.slim
#一覧画面に新規登録リンクを追加する
一覧画面(index.html.slim)に新規投稿画面へのリンクを設置します。
Bootstrap用にcssクラスを与えると、リンクをボタンのような外見にしてくれます。

```ruby:index.html.slim
h1 タスク一覧

= link_to '新規登録', new_posts_patch, class: btn btn-primary
```

Slimテンプレートでは、＝で始まる行はRubyコードの実行と出力をします。
link_toメソッドは、a要素を出力するメソッドです。
new_task_pathはURLヘルパーメソッドです。"/posts/new"というURL文字列を得られます。

#モデルの翻訳情報を追加する
投稿フォームを作る前に、下準備としてPostモデルの翻訳情報をconfig/locales/ja.ymlに追加。

```config/locales/ja.yml
ja:
  activerecord:
    errors:
      messages:
        record_invalid: 'バリデーションに失敗しました: %{errors}'
        restrict_dependent_destroy:
          has_one: "%{record}が存在しているので削除できません"
          has_many: "%{record}が存在しているので削除できません"
    models:
      post:投稿
    attributes:
      post:
      id: ID
      content: 投稿内容
      created_at: 登録日時
      updated_at: 更新日時
```

#新規登録画面用のアクションの実装
app/controllers/posts_controller.rbのnewアクションで、新規投稿画面の表示に必要な準備を行うようにします。
新しいPostオブジェクトを生成して、インスタンス変数@postに代入します。

```ruby:app/config/posts_controller.rb
  def new
    @post = Post.new
  end
```
アクションからビューに受け流しをしたいデータをインスタンス変数に入れることが、アクションの役割の一つです。

#新規投稿画面のプレビューを実装する。
newアクションに対応するファイルはapp/views/posts/new.html.slimです。
@postを利用し、form_withメソッドによって投稿フォームを表示します。
投稿を断念して一覧へできるように、一覧へのリンクも追加しています。

```ruby:app/views/posts/new.html.slim
h1 つぶやきの新規投稿

.nav.justify-content-end
  = link_to '一覧', posts_path, class: 'nav-link'

= form_with model: @post, local: true do |f|
  .form-group
    = f.label :投稿内容
    = f.text_area :content, rows:5, class: 'form-control', id: 'post_name'
  = f.submit nil, class: 'btn btn-primary'
```

form_withブロックの最後でsubmitヘルパーを呼んでいます。
ここで表示される、「登録する」という用語は翻訳情報のhelpersに定義されているため、@postの状態によってRailsが自動的に判断してくれているようです。
ですので、「投稿する」に変更しておきます。

これで、「一覧」と「新規投稿画面」を作ることができました！

#投稿アクションの実装
「投稿」アクションにデータを送ることができるようになりましたが、まだ処理を書いていません。
投稿アクションはapp/controllers/posts_controller.rbで、createアクションとして書いていきます。
「投稿フォームから送られてきたデータをDBに保存し、一覧画面に遷移する」という処理になります。

```ruby:app/controllers/posts_controller.rb
  def create
    post = Post.new(post_params)
    post.save!
    redirect_to posts_url, notice: "「#{post.content}」を投稿しました。"
  end

  private

  def post_params
    params.require(:post).permit(:content)
  end
end
```

ファイル後方のプライベートメソッドのpost_paramsメソッドは、セキュリティ上の理由で追加しました。
意図しないデータを送られないようにしている、Strong Parametersとよばれるものです。

安全化したpostパラメータをpost_paramsメソッドで取得し、それを使ってPostオブジェクトを作成します。
次に、これをsave!メソッドでDBに保存し、redirect_toメソッドで一覧画面に遷移させます。

redirect_toメソッドにはFlashメッセージを渡すことができます。Flashはリダイレクトの際に、次のリクエストに対してちょっとしたデータを伝える仕組みです。
Flashには、ハッシュの形でデータを渡すことができます。
Flashメッセージは、画面に表示させる必要があるので、共通レイアウトにコードを追加します。
nilや空白でないnoticeのフラッシュメッセージがあれば表示するという意味です。

```app/views/layouts/application.html.slim
    .container
      - if flash.notice.present?
        .alert.alert-success= flash.notice
```

試しに、新規投稿をしてみましょう。投稿を入力して、「新規投稿」ボタンを押すと…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/999125/0e246629-4669-762a-9abc-916dc8f44b8c.png)
一覧画面にリダイレクトされて、Flashも表示されました！
ブラウザを更新するとFlashが消えたので、DBへの登録とFlashの表示はうまくいったようです。

#
#参考
[現場で使える Ruby on Rails 5速習実践ガイド](https://www.amazon.co.jp/gp/product/B07JHQ9B5T/ref=ppx_yo_dt_b_d_asin_title_o03?ie=UTF8&psc=1)