現在Ruby on Rauls にて、Twitterのような投稿サービスを作っております。求職用のポートフォリオとしての制作です。
元々progateで勉強をしていたため入力フォームを「form_tag」で理解していました。そして今「form_for」or「form_with」へview/postのフォーム部分を入れ替えているところです。その最中、form_tagでは投稿した内容の編集機能は動いていたのですが、機能しなくなってしまいました。
自分で試したこととしては、
・routesをresourcesにする。(編集できるようになったが、編集した投稿とは別の投稿に変更が反映される等の不具合が起きたため、下記routesの状態に結果戻しました)
・form_forをURLで飛ばす、コントローラ名とアクション名で飛ばす、ルーティングで定義したもので飛ばす
などを試みました。
しかし、一向に解決できず、、
Rails.application.routes.draw do get "posts/index" => "posts#index" get "posts/new" => "posts#new" post "posts/create" => "posts#create" get "posts/:id/edit" => "posts#edit" get "posts/:id" => "posts#show" patch 'posts/:id' => 'posts#update' post "posts/:id/destroy" => "posts#destroy" post "users/create" => "users#create" get "signnup" => "users#new" post "login_guest" => "users#login_guest" get "login" => "users#login_form" post "login" => "users#login" post "logout" => "users#logout" get "users/index" => "users#index" post "users/:id/update" => "users#update" get "users/:id" => "users#show" get "users/:id/edit" => "users#edit" get "home/top" end コード
application.html.erb <!DOCTYPE html> <html> <head> <title>Read & Memo</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto" > <%= csrf_meta_tags %> <%= csp_meta_tag %> <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %> </head> <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css"> <body> <div class="header"> <div class="header-logo"> <%= link_to("「Read & Memo」", "/home/top") %> </div> <ul class="header-menus"> <% if @current_user %> <li> <span class="fa fa-user"></span> <%= link_to(@current_user.name, "/users/#{@current_user.id}") %> </li> <li> <span class="fa fa-pencil"></span> <%= link_to("投稿する", "/posts/new")%> </li> <li> <span class="fa fa-list"></span> <%= link_to("投稿一覧", "/posts/index")%> </li> <li> <span class="fa fa-users"></span> <%= link_to("登録者一覧", "/users/index") %> </li> <li> <span class="fa fa-sign-out"></span> <%= link_to("ログアウトする", "/logout", {method: :post}) %> </li> <% else %> <li> <span class="fa fa-user-secret"></span> <%= link_to("簡単ログイン", "/login_guest", {method: :post})%> </li> <li> <span class="fa fa-user-plus"></span> <%= link_to("新規登録", "/signnup") %> </li> <li> <span class="fa fa-sign-in"></span> <%= link_to("ログインする", "/login") %> </li> <% end %> </ul> </div> <%= yield %> </body> </html>
class PostsController < ApplicationController before_action :authenticate_user before_action :ensure_correct_user, {only: [:edit, :update, :destroy]} def index @post = Post.find_by(id: params[:id]) @posts = Post.page(params[:page]).per(5).order(created_at: :desc) end def show @post = Post.find_by(id: params[:id]) @user = User.find_by(id: @post.user_id) end def new @post = Post.new if @current_user == nil flash[:notice] = "ログインして下さい" redirect_to("/login") end end def create @post = Post.new(post_params) @post.user_id = @current_user.id if @post.save redirect_to("/posts/index") flash[:notice] = "投稿しました" else render("/posts/new") flash[:notice] = "投稿失敗" end end def edit @post = Post.find_by(id: params[:id]) end def update @post = Post.find_by(id: params[:id]) @post.user_id = @current_user.id if @post.update redirect_to("/posts/index") flash[:notice] = "投稿の編集をしました" else redirect_to("/posts/#{@post.id}/edit") end end def destroy @post = Post.find_by(id: params[:id]) @post.destroy redirect_to("/posts/index") flash[:notice] = "削除しました" end def ensure_correct_user @post = Post.find_by(id: params[:id]) if @post.user_id != @current_user.id flash[:notice] = "ユーザーが一致しません" redirect_to("/posts/index") end end private def post_params params.require(:post).permit(:content, :image, :user_id, :title) end end コード
post/new <div class="post-index"> <h1>新規投稿</h1> <% @post.errors.full_messages.each do |message| %> <div class="form-error"> <%= message %> </div> <% end %> <div class="post-new-container"> <%= form_for @post, url: posts_create_path do |f| %> <div class="posts-new-item"> <%= f.label :title, "タイトル(※必須)" %><br> <%= f.text_field :title %><br><br> <%= f.label :content, "感想・まとめ(※必須)" %><br> <%= f.text_area :content %><br><br> <%= f.label :image, "画像" %><br> <%= f.file_field :image %><br><br> <%= f.submit "投稿する" %> </div> <% end %> </div> </div> コード
posts/edit.html.erb <div class="post-index"> <h1>編集投稿</h1> <% @post.errors.full_messages.each do |message| %> <div class="form-error"> <%= message %> </div> <% end %> <div class="post-edit-container"> <%= form_for(@post, url: posts_create_path) do |f| %> <div class="posts-edit-item"> <%= f.label :title, "タイトル" %><br> <%= f.text_field :title %><br><br> <%= f.label :content, "感想・まとめ" %><br> <%= f.text_area :content %><br><br> <%= f.label :image, "画像" %><br> <%= f.file_field :image %><br><br> <%= f.submit "編集する" %> </div> <% end %> </div> </div> コード
posts/_form.html.erb <div class="post-new-container"> <%= form_for @post, url: posts_new_path do |f| %> <div class="posts-new-item"> <%= f.label :title, "タイトル(※必須)" %><br> <%= f.text_field :title %><br><br> <%= f.label :content, "感想・まとめ(※必須)" %><br> <%= f.text_area :content %><br><br> <%= f.label :image, "画像" %><br> <%= f.file_field :image %><br><br> <%= f.submit "投稿する" %> </div> <% end %> </div> コード
models/post.rb class Post < ApplicationRecord mount_uploader :image, ImageUploader validates :title, {presence: true} validates :content, {presence: true} validates :user_id, {presence: true} def user return User.find_by(id: self.user_id) end end コード
ActiveRecord::Schema.define(version: 2020_01_18_054634) do create_table "destroys", force: :cascade do |t| t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false end create_table "posts", force: :cascade do |t| t.text "content" t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false t.string "image" t.integer "user_id" t.string "title" t.float "rate" end create_table "sessions_users", force: :cascade do |t| t.string "name" t.string "email" t.string "password" t.string "image" t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false end create_table "users", force: :cascade do |t| t.string "name" t.string "email" t.string "password" t.string "image" t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false end end コード
また、routesにてupdate部分を
「
patch 'posts/:id/update' => 'posts#update'
」
のように変えると、下記のエラーが表示されます(その後、patch 'posts/:id' => 'posts#update'に戻してます)。
ちなみにform_tagに戻すと投稿の編集も普通に機能するため、余計に理解できない状態にあります。むしろform_tagのままでよければ全て解決なんですが、Rails 5.1 以降は推奨されていないようなので、現場に出たことがない自分としてはそれでいいのか判断しかねています。
また、posts_create_pathに向けてフォームの送信してる事に関しては、エラー画面下部に表示されてる内容から送信先HTTP Verbの「PATCH /posts/:id/update(.:format)」がposts_create_pathのなかに入れ子(?)のようになっていたので、そこに従って書いていました。
そのように記載する事に関しては深く考えがあったわけではありませんでした。
色々とおかしな書き方をしてるとは思うのですが、現状として解決したいのは投稿内容の編集をform_forかform_withで機能させることです。
自分では解決しかねております。ご教授いただけると幸いです。どうぞ、よろしくお願いします。
回答2件
あなたの回答
tips
プレビュー

