1
1

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 1 year has passed since last update.

【Rails】Twitterクローンを作ってみた 〜コメント機能の作成〜

Last updated at Posted at 2022-11-14

はじめに

【Rails】Twitterクローンを作ってみた 〜ツイート機能編〜の続きです。こちらを前提に進めていきますので、まだご覧になっていない方はそちらからご覧ください!※こちらはdockerでの環境構築を省きます。

サービス環境

  • ruby 3.0.0
  • Rails 6.0.4
  • docker
  • mysql 8.0.2
  • Slim, SCSS

コメント機能作成

条件

  • TweetをクリックでそのTweetのコメントが見られる(コメントページ)
  • コメントページの「コメント」をクリックでコメント新規作成に遷移できる
  • コメントを投稿するとコメントページにリダイレクト
    コメントモデルの作成し、Userモデル, Tweetモデルとコメントを関連付けさせてください。コメントもTweet同様140文字までとします。また、コメントモデルのテキスト部分のカラム名はtextとしてください。

実装流れ(簡略)

① Userモデル、Tweetモデルに紐付けたCommentモデル作成(textカラムを持つ)
② db:migrate
③ userモデル編集(has_many :comments, dependent: :destroy)
④ tweetモデル編集(userモデル同様)
⑤ commentモデル編集(バリデーションをかけてtextを最大140文字までとする)
⑥ commentsコントローラ作成、編集
⑦ tweetsコントローラ編集(showアクション)
⑧ routes.rb追記(ネスト)
⑨ comments/new.html.slim書く。cssも同様に。 ←難
⑩ tweets/show.html.slim書く。cssも同様に。

ツイート詳細ページ

スクリーンショット 2022-11-13 17.38.51.png

コメントページ

スクリーンショット 2022-11-13 17.41.43.png

ツイート詳細ページ(コメント後)

スクリーンショット 2022-11-13 17.42.00.png

解説

views/comments/new.html.slim

h4 コメントを投稿する
= form_with model: @comment, url: tweet_comments_path, local: true do |f|
  = f.hidden_field :tweet_id, :value => @tweet_id
  .c-group 
    = f.label :text
    = f.text_area :text, maxlength: 140, placeholder: 'コメントを記入してみよう!', class: "form-control", required: 'required'
  .btn-space  
    = f.submit nil, class: 'btn'
  .actions
    = link_to '戻る', root_path, class: 'cancel-button'

こちらはかなり苦戦しました。前回セクションのツイート機能作成の通りにhtmlを書けば良いのかと思っていたら、落とし穴でした。まずform_withタグで指定するモデルはcommentモデルです。モデルを指定しない場合、commentsコントローラでparamsを受け取れません。さらにurlでpathを渡します。urlを渡さない場合、モデルがurlを自動推測しますが、ここでは自動推測してくれません。

= f.hidden_field :tweet_id, :value => @tweet_id

こちらはcommentモデルがtweet_idというパラメーターに渡したいインスタンス(@tweet_id)を指定して、次のアクションに渡したい時に使用します。よって次のアクション(コメントの投稿)をした際のパラメーターをコンソールで見てみると以下のようになります。

Parameters: {"authenticity_token"=>"〜〜〜", "comment"=>{"tweet_id"=>"数字", "text"=>"私も苦戦しました。"}, "commit"=>"登録する", "tweet_id"=>"数字"}

comments_controller.rb

class CommentsController < ApplicationController
  before_action :find_tweet_id

  def new
    @comment = Comment.new
  end

  def create
    @comment = current_user.comments.build(comment_params)
    if @comment.save
      redirect_to tweet_path(@tweet_id), notice: "コメントを投稿しました。"
    else
      redirect_to new_tweet_comment_path(@tweet_id), alert: "コメントの投稿に失敗しました。"
    end
  end

  private

  def find_tweet_id
    @tweet_id = params[:tweet_id]
  end

  def comment_params
    params.require(:comment).permit(:tweet_id, :text)
  end
end

ここで肝となるのが一番最初のコードです。

before_action :find_tweet_id

ここで最初にパラメーターとして[:tweet_id]を受け取らないとcreateアクションでcommentがtweet_idを見つけられず、常にコメントの投稿に失敗し続けます。失敗している状態で、先程のhidden_fieldで作り上げたパラメーターを見てみましょう!

Parameters: {"authenticity_token"=>"〜〜〜", "comment"=>{"tweet_id"=>"", "text"=>"私も苦戦しました。"}, "commit"=>"登録する", "tweet_id"=>"数字"}

commentのtweet_idが空になっていますよね。注意しましょう!

実装を通して学んだこと

1. form_withタグのmodel指定とurl指定

今まではmodel指定のみであったが、今回はurl指定も必要なことを学びました。commentは2つのモデルと紐づいており、自動的に推測してくれないと判明した際はurl等の指定も同時にしてあげなければならないことを学びました!

2. hidden_fieldタグ

このタグによって次のアクションに渡したいパラメーターやインスタンスを指定することができるということを学びました。今回のコメント機能は常にツイートに紐付いているため、ツイートのidを常に考慮しなければなりませんでした。

3. ルーティングのネスト

resources :tweets do
  resources :comments
end

tweetモデルに紐づくcommentモデルのルーティングは上記のように書けます。

感想

今回はかなりつまづきました。htmlでのform_withタグではurl指定をしておらず永遠にエラーが出る状況が続きました笑
hidden_fieldタグを調べながら書き、tweet_idをパラメーターで渡せる状況にしたものの、commentsコントローラではbefore_actionとしてtweet_idを渡しておらずパラメーターのtweet_idが空で渡されてしまっており、何度もエラーを出しました。。
エラーを出し、調べて試してみてうまく動くという経験はかなり大事なものだと感じました。今後こういったエラーが出てもすんなり対応できると思います!
次回は画像アップロード機能の作成についてアウトプットしていこうと思います!読んでいただきありがとうございました。

参考記事

1
1
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
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?