headerに投稿ページを作ることで、どのページでも投稿機能が使える
遭遇したエラーやつまづいたところ
・ヘッダーに投稿フォームを置いたのでページによっては想定とは別なコントローラーが呼ばれる
・エンターキー送信
・二つのモデルを一つのフォームにまとめる
model
validates :author, presence: true
validates :title, {presence: true, length: {maximum: 255}}
has_one_attached :image
has_many :impressions
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(感想)
投稿作成
<% 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
でもいいみたいです
エンターキー制限
type="button" onclick="submit();"
controller
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"
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だと思っていたら
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)
よんでくれてありがとう