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

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

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

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

Ruby

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

バリデーション

Validationとは特定の入力データが、求められた条件に当てまっているかをチェックするために使われます。

ルーティング

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

Q&A

解決済

2回答

1332閲覧

redirect_backとrenderによりレンダリングされる際のルーティングの違い。

punchan36

総合スコア105

Ruby on Rails 5

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

Ruby

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

バリデーション

Validationとは特定の入力データが、求められた条件に当てまっているかをチェックするために使われます。

ルーティング

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

0グッド

0クリップ

投稿2021/02/19 07:26

編集2021/02/20 01:34

前提・実現したいこと

ユーザーの投稿に対するコメント機能を実装し終えました。
このコメント機能に対する文字数制限とエラーメッセージを以下の様に設定しています。

comment.rb

class Comment < ApplicationRecord validates :body, {presence: true, length: {maximum: 100}} belongs_to :user belongs_to :post end

posts/show.html.erb

<% @comment.errors.full_messages.each do |message| %> <div class="form-error"> <%= message %> </div> <% end %> <div class="post-show-comment-field"> <%= form_for([@post, @comment]) do |f| %> <%= f.text_area :body, :placeholder => "Write a comment…", :rows => 3, :cols => 80 %> <%= f.submit "Comment" %> <% end %>

comments_controller.rb

class CommentsController < ApplicationController def create @comment = Comment.new(comment_params) @post = @comment.post if @comment.save @post.create_notification_comment!(@current_user, @comment.id) redirect_back(fallback_location: post_comments_path) else  @user = @post.user render ("posts/show") end end end

これで一応動きはするのですが、ルーティング周りの仕組みがよく分かりません。

同じcomments_controllerのcreateアクションを動かすのでも、
redirect_back(fallback_location: post_comments_path) とすると posts/#{@post.id} に、
render ("posts/show") とすると posts/#{@post.id}/comments と、
別々のルーティングにそれぞれレンダリングされますが、この理由がよく分かりません。
(個人的には、 render の際にも redirect_back の時同様 posts/#{@post.id} にレンダリングして欲しかったです。)

redirectは別のリクエストを出す(元のコントローラ --> ルーティング --> コントローラ --> ビュー)のに対して、
renderは指定したビューを表示するのみ。(元のコントローラ --> 指定したビューファイル )
と言う事は学んだのですが、まだモヤっとしています。

どなたかご教授いただければ幸いです。

補足

文字数制限自体に関しては、そもそもビューにて以下の様に :maxlength => 100 を記述する事で解決出来たので、こちらで実装しようかと思っています。
ただ上記の様にモデルにてバリデーション関連を組み立てていた際にどうしても腑に落ちない部分がありましたので、質問させて頂きました。

posts/show.html.erb

<%= form_for([@post, @comment]) do |f| %> <%= f.text_area :body, :placeholder => "Write a comment…", :rows => 3, :cols => 80, :maxlength => 100 %> <%= f.submit "Comment" %> <% end %>

補足情報(FW/ツールのバージョンなど)

ruby 2.6.4p104
RubyGems 3.0.3
Rails 5.2.3

追記

routes.rb

get "posts/:id" => "posts#show" resources :posts do resources :comments, only: [:create, :destroy] end

rails routesの結果

Prefix Verb URI Pattern Controller#Action post GET /posts/:id(.:format) posts#show PATCH /posts/:id(.:format) posts#update PUT /posts/:id(.:format) posts#update post_comments POST /posts/:post_id/comments(.:format) comments#create

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

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

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

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

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

winterboum

2021/02/20 01:03

(私が答えられるかわかりませんが) routes.rb か rails routesの結果かを載せたほうが良いかと。
punchan36

2021/02/20 01:35

有難うございます。大事な部分を書いておりませんでした。 追記いたしましたので、可能であればご助言頂けますと有難いです。
guest

回答2

0

/posts/:post_id/commentsCommentsController#create へ来た時のURL は '/posts/:post_id/comments' になっています。
そこに「相対URL」な "posts/show" なので なんかおかしくなったのかな。。。
なぜこうなったか、はわかりませんが、posts/#{@post.id} へ行かせるなら
post_path(@post) とか controller: :posts, action: :show とか "/posts/#{@post.id}"でしょうか。

投稿2021/02/20 10:01

winterboum

総合スコア23333

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

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

punchan36

2021/02/20 12:08

有難うございます!なるほどです…。 この様に親子関係にあるモデルが関連した処理を扱う場合、ちょっと render の挙動が普段と違ったので戸惑いました。 そもそもelseより手前でコメントが上手く保存された場合、post_comments つまり /posts/:post_id/comments に飛ぶように記述していますが、実際は posts/#{@post.id} に飛びます。これはデフォルトと言いますかそう言う設定なのでしょうか…?
punchan36

2021/02/22 13:01

色々と勘違いをしていた部分もありましたが、その後理解出来ました。 有難うございました!
guest

0

ベストアンサー

質問の意図が読み取れているのか不安ですが、

render "posts/show" が呼ばれるのは @comment.save に失敗した時です。
このとき、@comment にはエラーの内容が含まれています。

それを利用して入力の修正を促すため、
その場(/posts/:post_id/comments)で render しているのではないでしょうか。
(リダイレクトさせると @comment のエラー内容は参照できない)

POST /posts/:id でコメントの投稿を受け付ければ
render "posts/show" のURLは /post/:id になりますが、
REST的に良くないです。

投稿2021/02/20 07:38

neko_daisuki

総合スコア2090

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

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

punchan36

2021/02/20 12:07

有難うございます!なるほどです…。 ただコメントが保存された場合(elseの上)の処理を redirect_back(fallback_location: post_comments_path) から render ("posts/show") に変えても、やはり同様に posts/#{@post.id}/comments に飛んでしまうのですよね。 今回はビューにて :maxlength => 100 を記述すれば済む話でしたので困ってはいないのですが、仕組みの理解の部分でモヤっとしてしまいます…。
neko_daisuki

2021/02/21 09:46

URLと関連付けられるのはコントローラーのアクションです。描画するビューではありません。 成功の場合、投稿ページ -> /posts/:post_id/comments (ここでリダイレクト)-> /posts/:id(ここでrender) 失敗の場合、投稿ページ -> /posts/:post_id/comments (ここでrender) と遷移してます。最後にrenderしたアクションに対応するURLがアドレスバーに表示されます。 少しずれるかもしれませんが、以下の記事が参考になるかもしれません。 https://qiita.com/yuyasat/items/49e3296f3c64fccc7811 (この記事では失敗の場合もrenderするなと言っています)
punchan36

2021/02/22 08:00

有難うございます! 認識が合っていると良いのですが、まとめますと以下の様な仕組みでしょうか。 コメントを送信すると @comment.save がある comments コントローラの create アクションが動くので、それに該当するurlである /posts/:post_id/comments にまず渡る。 ・redirect_backを使う場合。 redirect_back でその「直前のページ」にリダイレクトさせているので /posts/:id に渡る。尚保存に失敗した場合、@comment のエラー内容は参照出来ないのでエラーメッセージも表示されない。 ・renderを使う場合。 render を指示したのは comments コントローラの create アクションなので、それに該当するurlである /posts/:post_id/comments に単純に渡る。保存に失敗した場合エラーメッセージは表示される。
punchan36

2021/02/22 13:00

よく理解出来ました。有難うございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問