LoginSignup
3
1

More than 3 years have passed since last update.

【フリマアプリ】商品詳細ページのコメント機能(第2回)〜ルーティング編〜

Last updated at Posted at 2020-05-02

 某スクールにおいて、チーム開発で、フリーマーケットアプリを作成中であり、使用した技術について公開しています。
※初学者のため、ミスや認識違いが多々あると思いますがご了承ください。

商品詳細ページにコメント機能を実装しました。

全部で7回に分けて記事を投稿しています。

内容 url
第1回 モデル、マイグレーション編 https://qiita.com/sho_U/items/03108801146e65d58413
第2回 ルーティング編 https://qiita.com/sho_U/items/5c829b3060be2cce919a
第3回 コントローラー編 https://qiita.com/sho_U/items/8528f336cf0d470cd719
第4.1回 ヴュー編(一覧表示) https://qiita.com/sho_U/items/6190562270c722956547
第4.2回 ヴュー編(インプットフォーム) https://qiita.com/sho_U/items/67c2ede4fc6c605283e2
第5回 jquery編 https://qiita.com/sho_U/items/d72b60114f76380d05f6
第6回 ajax編 https://qiita.com/sho_U/items/caed9b1471e63d43dd3a

〜コード全文〜https://qiita.com/sho_U/items/310ac5b653bdfcb99a2c

ルーティングについて

必要なルーティングについて

ルーティングを作成するにあたり、遷移先、つまりコントローラーのアクションはどういった物が必要そうか検討しました。

1.comments#create(createアクション)

 投稿フォームから、コメントを送信するためのアクション
※ちなみに、商品詳細ページが、コメント投稿画面を兼ねており、(item#showで @comment = Comment.new を定義しているためnewアクションは不要。@comment = Comment.newを定義する理由は、空の@commentを作成し、form_withの遷移先を自動で判別させるため)

2.comments#update(updateアクション)

コメントを仮削除するためのアクション。なぜ、削除なのにcreateなのかといいますと、本アプリは仕様上、1回目のコメント削除は、仮削除と言う形で、削除せずデーターベースに保存しておき、復元できるようにしています。よって、本来の意味は削除ではなく、仮削除状態へ更新するという動作になります。(ビュー上は、以下のように表示するようにしています。)
ea35e3c4df00a10ac38a3bf51ee10280.png

3.comment#restore(restoreアクション)
仮削除したコメントを復元させるためのアクション。

4.comment#destroy(destroyアクション)
仮削除したコメントを完全に削除するためのアクション。

以上の4つのアクションに遷移するための、ルーティングを作成する必要がありそうです。

update,destroyに対するルーティング

では、必要なルーティングが洗い出せたところで、それぞれどのように記載するか検討します。
resotore以外の、create,destroy,updataは、Railsで基本となる7つのアクションに含まれるため、まずはそちらから検討します。
シンプルにresouresで作成した場合のルーティングは以下の通りです。

routes.rb
resources :comments, only:[:create,:update,:destroy]

作成されるルーティング
272ad84a38eaaf7d7f3f02a8f3acda0d.png
a58b7f023fb68dbaf23d6cff0f8ebb61.png

resourcesから生成されたルーティングで、対応可能か検討します。
ルーティングを作成する上で、考慮しなければいけない事は、コントローラーの各アクションへ遷移する際にpathからparamsとしてデーターを送信する必要があるか、ということです。

上記の、pathを比較するとcreate以外は、末尾に/:idが付与されているのがわかると思います。例えば、updateアクションは、”/commnets/:id"となっており、実際のURLは、 "(略)/commnets/5" のように:idの部分に、文字列が記載されます。

 この場合は、アクションに対し、paramsというハッシュに、キーはid,バリューは"5"を格納し、

params = {id: "5"}

という形式で送信されます。

受け取ったアクションでは、

pramas[:id] 
=> "5"

で、送られてきたバリューを取得することができます。

では、なぜこのような値の受け渡しが必要なのでしょうか。

「create」と、「update,destroy」の両者の違いは、createは無からコメントを作成するのに対し、update,destroyは、現に存在するコメントに対して、行うアクションであるということです。
 言い換えると、アクションを行う対象のコメントを特定するための、何らかの情報が必要ということです。この役割を、pathに記載された:idの部分が担うわけです。

paramsを使用しなければ、例えばビュー画面で
59519a948d6e9bdbd44ffa0dfa399d34.png
このような、入力フォームを設ける事によって、強引に情報を送ってしまう事は可能であるとは思います。が、ユーザービリティは格段に落ちると思います。

しかし、例えば削除ボタンのlinkタグを以下のように記載すると(@commentには、id:5のコメントのインスタンスが格納されているとします)

= link_to '削除する', "/comments/#{@comment.id}" ,method: :patch

# わかりやすさのためprefixは使用していません。

リンクボタンをクリックした段階で、自動的に対象コメントのidである ”5” がコントローラーに送信されるわけです。
こっちの方が、ユーザーにとっても親切です。

ということで、update,destroyについてはresouresによって作成されるルーティングを使用することで実装できそうです。

createに対するルーティング

では、次にcreateに対するルーティングについて検討したいと思います。

createは先ほども説明した通り、対象となるコメントは必要ありません。
では、上記のように、" /comments "というpathで良いでしょうか?

ここで、第1回の記事を振り返ります。
https://qiita.com/sho_U/items/03108801146e65d58413

class CreateComments < ActiveRecord::Migration[5.0]
  def change
    create_table :comments do |t|
      t.references :item, null: false, foreign_key: true
      t.references :user, null: false, foreign_key: true
      t.integer :delete_check,default: 0
      t.string :comment
      t.timestamps
    end
  end
end

Commentモデルのマイグレーションは上記のようになっていました。
これを、データーベース上で表すと
5bf6ad956ad40fad5ea7464455040d66.png
このようなレコード構造となります。
これらの、カラムのうち「id」 「created_at」 「updated_at」 については、コメント作成時に自動で作成されて格納されます。
「delete_check」については、コメント作成時は、"0"が格納されるようにマイグレーションに定義しています。

「usrer_id」 は、コメント作成者のidが格納されるのですが、これは、コントローラー側で、deviseの機能により現在のログインユーザーのidを格納することが可能です。(コントローラー編で説明)

「comment」(注:commentsテーブルのcommentカラムという意味です。ややこしくてすみません)については、フォームに入力された内容がparamsとして、コントローラーのcreateアクションに受け渡されます。

残る「item_id」カラム、これはコメントと商品を結び付けて、どの商品に対するコメントなのかを特定するためののカラムなのですが、フォームには、コメント内容しか入力する欄がありません。そこで、何とかして、item_idをコントローラーにparamsとして送り届ける必要があります。

つまり、createはupdate,destroyと違い、どのコメントに対してかという情報は必要ありませんが、代わりに、どの商品に対してかとう情報をコントローラーに送る必要があるのですね。

update,destroyと同じように、pathに情報を組み込んで、送るという手法を用いようとしたら現在の

 /comments

では不可能ですね。
そこでpathに:id が付与されるように、ルーティングの記載を変える必要があります。

そこで、ルーティングのネストという手法を用います。

今itemsコントローラーに対するルーティングが以下のように記載されているとします。

routes.rb
resources :items 

このルーティングに対し、入れ子構造でcommentのルーティングを記載します。

routes.rb
resources :items do
  resources :comments,only[:create]
end

すると、以下のようなpathが生成されます。

/items/:item_id/comments

これで、 :item_id のところにitemのid情報を埋め込むことにより、params = {item_id: "値" } というハッシュで対象商品を特定するための情報を送れそうです。

これに、update,destroyを加えて

routes.rb
resources :items do
  resources :comments,only: [:create,:update,:destroy]
end

以下が生成されたルーティングです。
efecf4cacf4918dc65cad861d997d67c.png

このように記載することにより、目的は達成されそうです。、、、といいたいところですが、今回は別の方法を採用することにしました。
見てもらったらわかる通り、update,destroyに遷移するためのpathが不必要に長くなっているんですね。この2つは、どのコメントかを特定すればいいだけなので、さらにそのコメントがどの商品に対するものかという情報(/items/:item_id/の部分)は不要です。無駄に冗長的にすることで、バグの発生リスクや、見通しが悪くなる可能性が生じます。commentsのresourcesをネストするものと、ネストしないものに分けるといった方法もありそうですが、結果として今回は、

routes.rb
  resources :items do
  resources :comments, only:[:create,:update,:destroy] do

という形でネストせずに組みました。当然、先ほど説明したとおり、createに対し生成されるpathは、

/comments

となりURLに情報を埋め込むことはできなさそうです。
どのようにして、paramsとして、itemのidを送ったのかは、第4.2回の記事で紹介いたします。

restoreに対するルーティング

では、最後にrestore対するルーティングについて検討したいと思います。
restoreについては、railsの基本アクションではなく、resouresでは作成できないため手動で作成する必要があります。
また、コメントを復元する動作ももupdate,destroyと同じく、対象となるコメントを特定する必要があります。
そのため、

/comments/:id/restore 

というpathを生成する必要があります。そこで、下記のようにcommentsのルーティングにネストさせることにしました。
手動でルーティングを作成するときには、ネストする際に member do で入れ子にすることにより、:idが付与されます。

routes.rb
  resources :comments, only:[:create,:update,:destroy] do
    member do
      get 'restore'
    end
  end

復元といっても、何かしらデーターを送信するわけではなくデーターベースにある情報を元に表示するだけなので、httpメソッドは「get」にしました。

念のため、生成されたpathを確認したところ
a9c090618a000f9d7909916ced3b712b.png

目的のpathが生成されていました。

ちなみにネストの方法はmember doの他にcollection doという方法もあり、後者の場合は、:idが付与されません。

routes.rb
  resources :comments, only:[:create,:update,:destroy] do
    collection do
      get 'restore'
    end
  end

6ea327bb289e69ce696d7b448ae2d787.png

次回(第3回)は、コントローラー編となります。

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