質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

POST

POSTはHTTPプロトコルのリクエストメソッドです。ファイルをアップロードしたときや入力フォームが送信されたときなど、クライアントがデータをサーバに送る際に利用されます。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

ルーティング

ルーティングとは、TCP/IPネットワークにおいて、目的のホストまでパケットを送る為のパス選定のプロセスを言います。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

Q&A

解決済

1回答

3013閲覧

Rails 新規投稿が上書きされてしまう

Atamak

総合スコア5

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

POST

POSTはHTTPプロトコルのリクエストメソッドです。ファイルをアップロードしたときや入力フォームが送信されたときなど、クライアントがデータをサーバに送る際に利用されます。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

ルーティング

ルーティングとは、TCP/IPネットワークにおいて、目的のホストまでパケットを送る為のパス選定のプロセスを言います。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

1グッド

1クリップ

投稿2020/09/08 03:29

編集2020/09/08 06:44

解決したいこと・現状

Rails にて掲示板を作成中です。
新規投稿機能(post)を実装後、編集機能を追加しようと思い、editアクションとupdateアクションをpostコントローラーに追加しました。

すると今まで新規投稿フォームから新規投稿できていた実装が、
全て上書きされてしまう状態になってしまいました。
(例:投稿内容「あいう」と投稿する→新規投稿フォームで「かきく」と入力し投稿すると「あいう」が「かきく」に上書きされてしまう)
エラー画面は出ておらず、ターミナル上ではupdateアクションが実行されたという記述になっています。

編集画面はedit.html.erbとして用意しています。
編集は問題なくできるのですが、新規投稿ができなくなってしまった状況です。

仮説

状況としては、createアクションが呼ばれずupdateアクションになってしまっているので
form_withの記述の誤りか、ルーティングがおかしいのかと仮説しています。
ルーティングがresourcesを使用しているので問題ないとは思っているのですが、
原因がわかりません。

コメントいただいた内容を元に、topics_controller.rbの@postを見返し、

@post = Post.find(params[:id])

があるからupdateされてしまうのではないかと考えコメントアウトしてみたら新規投稿はできるようになりましたが、
showページの「edit」へのリンクが消えてしまいました。

初学者で理解が浅い点があり、申し訳ありませんが
お助けいただけると嬉しいです。

よろしくお願いいたします。

コード

(show.html.erb)Topicはpostのタイトル要素です。

<div class="new-post"> <h2>New post</h2> <%= form_with(model: [@topic, @post], local: true) do |f| %> <p><%= f.text_area :body %></p> <%= f.submit "Post" %> <% end %> </div>

同ファイル(編集リンク箇所)

<div class="posts"> <% if @posts %> <% @posts.each do |post| %> <div class="post-content"> <div class="post-body"> <%=safe_join(post.body.split("\n"),tag(:br))%> </div> <div class="post-info"> <div class="post-user"> from:<%= link_to post.user.nickname, "/users/#{post.user_id}" %> </div> <div class="post-date"> date:<%= post.created_at %> </div> <div class="post-edit"> <% if current_user.id == @post.user_id %> <%= link_to "edit", edit_topic_post_path(post.id), method: :get %> <% end %> </div> </div> </div> <% end %> <% end %> </div>

(edit.html.erb)

<div class="post-edit-page"> <div class="post-edit-form"> <%= form_with(model: @post, url: topic_post_path, local: true) do |f| %> <%= f.text_area :body %> <%= f.submit "Edit" %> <% end %> </div> </div>

(posts_controller.rb)

class PostsController < ApplicationController def create @post = Post.create(post_params) redirect_to "/topics/#{@post.topic.id}" end def edit @post = Post.find(params[:id]) end def update post = Post.find(params[:id]) if post.update(post_params) redirect_to topic_path else render 'edit' end end private def post_params params.require(:post).permit(:body).merge(user_id: current_user.id, topic_id: params[:topic_id]) end end

(topics_controller.rb)

def show @topic = Topic.find(params[:id]) @post = Post.new @posts = @topic.posts.includes(:user) @post = Post.find(params[:id]) end

(routes.rb)

resources :topics, only: [:index, :new, :show, :create] do resources :posts, only: [:create, :edit, :update] end end
necocoa👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

necocoa

2020/09/08 04:25

topics_controller.rbのshowアクションの情報を追記お願いします!
HiroshiUeki

2020/09/08 04:44 編集

form_withに渡している`@post`が重要になってくるので、necocoaさんがおっしゃるように、showアクションの情報を書いていただければなにかわかるとおもいます。 [【Rails】form_with/form_forについて【入門】 - Qiita](https://qiita.com/snskOgata/items/44d32a06045e6a52d11c#%E6%96%B0%E3%81%97%E3%81%8F%E4%BD%9C%E3%82%89%E3%82%8C%E3%81%9F%E3%82%82%E3%81%AE%E3%81%8C%E6%B8%A1%E3%81%95%E3%82%8C%E3%81%9F%E5%A0%B4%E5%90%88)
Atamak

2020/09/08 05:06 編集

コメントいただきありがとうございます! showアクションについての記述を追加しました。 topicに対するコメントのようなイメージで設計していたので、topicコントローラー内のshowアクションに@postに関する定義しをています。 新規投稿機能のみの場合は、postコントローラーにcreateアクションのみ記述していました。
necocoa

2020/09/08 06:25

> showページの「edit」へのリンクが消えてしまいました。 この対象となるコードを掲載いただけますか?
Atamak

2020/09/08 06:43 編集

気が利かず申し訳ありません; 質問フォームの方に掲載させていただきます!
guest

回答1

0

ベストアンサー

質問への回答ありがとうございます。

今回重要な点はshow.html.erbtopick_contoller.rbのshowアクションです。
form_withタグではmodel: [@topic, @post]に渡した@postの内容によってcreate or updateに切り替えてくれます。

@postがnewしただけのオブジェクトだった場合、create
@postにPostデータが入っている場合、updateとなります。

以前まで正常に動いていた理由はupdateを作っていなかったため、毎回createになっていたのかと思います。(以前のコードがわからないため予想です。)

続いて修正点です。

ruby:topicks_controller.rb

1 def show 2 @topic = Topic.find(params[:id]) 3 @post = Post.new 4 @posts = @topic.posts.includes(:user) 5 @post = Post.find(params[:id]) 6 end

こちらのアクションで@postに二度値を代入しています。
今回間違えていたポイントは@post = Post.find(params[:id])でDBからpostのデータを取得し@postに入れていたため、updateとしてフォームが判定していました。

@postには新規作成のフォームにわたすオブジェクトとして@post = Post.newでnewしただけの空のオブジェクトを渡しているため@post = Post.find(params[:id])は必要ありません。

また、topick_controllerでのparams[:id]はTopickのidが入ります。
今回はたまたまpostでもidが一致しているためPost.find(params[:id]で取得できていますが、これは本来取得したいPostを取得していないため気をつけてください。

なにか他にわからない点がありましたらスレッドにて再度質問をお願いします。

追記

同ファイル(編集リンク箇所)
<% if current_user.id == @post.user_id %>
こちらが@postではなく、postになります。
なので、こちらに修正すればeditが表示されるかと思います!
<% if current_user.id == post.user_id %>

みやすさのためrubyだけのコードにしてみます(実際はlink_toはerb内でしか使えません)

ruby

1@posts.each do |post| 2 if current_user.id == @post.user_id 3 link_to "edit", edit_topic_post_path(post.id), method: :get %> 4 end 5end

eachでpostsをループしており、postという変数に代入しています。
そのpostのuserが自分かどうかをif文で判定しています。
if current_user.id == @post.user_id
その部分を@postにしています。
これはeachで渡したpostとは全く別の変数と認識されています。

以前までは @post = Post.find(params[:id]というコードが合ったため@postのデータが存在しeditが表示されておりました。
しかし前述したとおり、これは本来対象とするpostではないです。

また、1つの@postのデータのため以前のコードでは、
「複数のpostが作成されていて、editが表示されていても」すべて同じpostのeditになっていたはずです。

これからは@がつくインスタンス変数と、なにもつかないローカル変数を注意してみてみると良いと思います。

投稿2020/09/08 05:27

編集2020/09/08 07:00
necocoa

総合スコア209

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Atamak

2020/09/08 06:36

necocoa様 とてもわかりやすい解説をいただきありがとうございます! @postの定義について理解が深まりました! @post = Post.find(params[:id])を削除することで新規投稿はできるようになったのですが、 今度はeditリンクが消えてしまいました。 本来はログインしているユーザーが書き込みしたユーザーであれば日付の横の□内に「edit」と表記されます。 参照画像 https://i.gyazo.com/a348d2575f788f00a4604c85208fb3fc.png これはeditアクションとupdateアクションをtopicコントローラーの方で定義しなければならないのでしょうか?
necocoa

2020/09/08 07:00 編集

コメントにはコードをかけないようなので、元の回答の方に質問への回答を追記しました。 ご確認ください。
Atamak

2020/09/08 08:25

再度ご回答頂きありがとうございます! おっしゃる通り修正したら、editが表示されました! 解決方法のみならず解説&アドバイスまでしていただき本当に感謝いたします! これからも学習頑張ります!
necocoa

2020/09/08 08:34

よかったです!応援してます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問