1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-12-20

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のところのbuildnewでもいいみたいです

railsのnewとbuildの違い

エンターキー制限

.rb
type="button" onclick="submit();"

Enterキーを無効にする方法

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)

よんでくれてありがとう

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?