複数のコントローラーをくぐり抜ける投稿画面作成


headerに投稿ページを作ることで、どのページでも投稿機能が使える

遭遇したエラーやつまづいたところ
・ヘッダーに投稿フォームを置いたのでページによっては想定とは別なコントローラーが呼ばれる
・エンターキー送信
・二つのモデルを一つのフォームにまとめる


# model

```book.rb
      validates :author, presence: true 
      validates :title, {presence: true, length: {maximum: 255}}

      has_one_attached :image
      has_many :impressions
```

```impression.rb
    validates :story , presence: true
    validates :impressions, presence: true

    belongs_to :book
```

book.rb にて
`has_many :impressions`
impression.rb　にて
`belongs_to :book`
と、しているのでコントローラーで

```
@book.impressions.build
```
@book起点でimpressionが作成できる

#### 想定とは違うコントローラーが呼び出される問題
```
<% book = Book.new %>
```
今回作成した投稿フォームはヘッダーに置いてあり、ユーザー画面に行くと別なコントローラーが呼ばれてしまう。
book_controllerに処理を書いてしまうと、中身がusers_controllerをあてにしている画面ではusers_controllerが呼び出されてbook_controllerが呼ばれなくてエラーになってしまうのでその対策としてHTMLに直接記述しています


こういう時のためにapplicationに書いて各controllerにbefore_actionで呼び出しの制限をかけるのだけれど直接記述してある方が一箇所で済んで早い？

## table
ひとつの本に、複数の感想が付くという形にしたいため二つのテーブルに分けています
booksテーブルには:titleと:author（著者）
impressionテーブルには:story（惹句）と:impressions(感想)


## 投稿作成

```_new.html.rb
    <% book = Book.new %>
    <%= form_with url:'/books/create', local: true, method: :post  do |form| %>
        <%= form.file_field :image %>
        <%= form.text_field :author, :placeholder => "作者の名前" %>
        <%= form.text_field :title, :placeholder => "本のタイトル" %>

    <%=  form.fields_for book.impressions.build do |field| %>
        <%= field.hidden_field :user_id ,:value =>  @current_user %>
        <%= field.text_area :story, :placeholder => "あらすじ"%>
        <%= field.text_area :impressions, :placeholder => "本の感想"%>
    <button type="button" onclick="submit();">送信</button>
    <% end%>
  <% end%>
```

### build
`fields_for`のところの`build`は`new`でもいいみたいです
 
[railsのnewとbuildの違い](https://qiita.com/sukechansan/items/6bae532b4f678fdcf87d)


### エンターキー制限

```.rb
type="button" onclick="submit();"
```
[Enterキーを無効にする方法](https://qiita.com/mimoe/items/89b317be5e38bfbc44ee)

# controller

```books_controller.rb
      def create
        @book = Book.new(
          title: params["title"],
          author: params["author"],
          image: params["image"],
          user_id: @current_user.id,
        )
      @book.image.attach(params[:image])

      impression = @book.impressions.build(
        story: params["impression"]["story"],
        impressions: params["impression"]["impressions"],
        user_id: @current_user.id,
        book_id: @book.id,
      )
      if @book.save
        redirect_to "/index"
      else
        @erorr_message = "送信失敗しました。"
        render "new"
      end
    end
```
#### impression.newではなく@book.impressions.build
・読んで分かるかかわり合いを持たせたい
・二つのテーブルにまたがったフォームなので作るときは二つのデータとも一緒に作りたいと思っている
book→impression
の順番でコントローラーには記述するのでimpressionのsaveに失敗した場合bookをsaveしているとelseの処理に@book.dstroyと記述しないといけないから

「buildはcreateに近いが、databaseにはこのタイミングで保存されない、という違いがある」

## 初歩的なエラーでオチ
updateをするformで

`No route matches [PATCH] "/users/3/user/3/update"`
と言われましたがあんた
勝手に探しているけれど探して欲しいurlはこっち
`url: "user/#{@current_user.id}/update"`

```route.rb
    patch  "user/:id/update" => "users#update"
```
だからといって

```
 url: "users/update"
```
こうすると
`No route matches [PATCH] "/users/3/users/update"`
こうなって

```
url: "/update"
```
こうすると
`No route matches [PATCH] "/update"`
こうくる

何がおかしいと思ってたら先頭に / がなかっただけですな
しかも"/update"この時はきちんとつけているから気づきませんでした。

ので、

```
url: "update"
```
こうすれば先頭に/users/3/がつくと思って実行
`No route matches [PATCH] "/users/3/update"`
しかしエラー
なんてことはなくroutes.rbの記述がusersだと思っていたら

```routes.rb
   patch  "user/:id/update" => "users#update"
```
になっていただけでした。

### 参考にさせていただきました

[fields_forの上手な使い方]
(https://qiita.com/kouuuki/items/5daf2b5f34273d8457f7)

[【Rails 5】(新) form_with と (旧) form_tag, form_for の違い]
(https://qiita.com/hmmrjn/items/24f3b8eade206ace17e2)

[Rails5のform_withのデータの行き先]
(https://qiita.com/kakiuchis/items/9ab8dc212ed5c57a2ddd)

よんでくれてありがとう