前提
Railsにて、単語帳アプリを作成しました。
登録される単語をWordモデルとし、お気に入り機能を実装するため、Wordモデルと紐づくFavoriteモデルがあり、以下のようなアソシエーションが組まれています。
class Word < ApplicationRecord
has_many :favorites, dependent: :destroy
end
class Favorite < ApplicationRecord
belongs_to :word
end
dependent: :destroy
で、親モデルが削除されたときは、それに紐付いている子モデルも削除されるように設定。
単語をお気に入りに追加もしくはお気に入りから外す際には、以下のアクションが働きます。
class FavoritesController < ApplicationController
before_action :set_word
def create #お気に入りに追加する
@favorite = Favorite.create(word_id: @word.id)
end
def destroy #お気に入りから外す
@favorite = Favorite.find_by(word_id: @word.id)
@favorite.destroy
end
private
def set_word #パラメーターとして送られてくるword情報をインスタンス変数に代入
@word = Word.find(params[:word_id])
end
end
予定している動きとしては、以下の通りです。
- 「お気に入りに追加」ボタンを押すと、その単語の情報が
FavoritesController
にパラメーターとして送られてくる。
(params(送られてきたパラメーターをハッシュのような構造で格納したもの)によって、設定したルーティングのURLに含まれているword_idがFavoritesコントローラーのcreateアクションへ渡される) -
before_action
により、コントローラで定義されたアクション(今回の場合、createアクション)が実行される前に、set_wordアクションが実行され、findメソッド
を使用し引数で指定したidのレコードを取得し、インスタンス変数@word
に代入。
(引数では、送られてきたパラメーターに含まれるwordのid情報をparams[:キー名]
で取り出している) - createアクションが実行され、word_idには、パラメーターとして送られてきたwordのidを値に持つインスタンス(お気に入り)を生成し、インスタンス変数
@favorie
に代入。
この動きを実現させるために、上記のリスト1に関わる、「wordのid情報をパラメーターとしてURLに含める」という作業が必要になります。その上で、コントローラーがその情報を受け取り、アクションが実行され、お気に入りインスタンスが生成されるからです。この場合、ルーティングのネストを意識しなければなりません。
ルーティングのネスト
ネストとは入子構造のこと。
まず、ネストを意識せずにルーティングを記述すると以下の通り。
Rails.application.routes.draw do
resources :word
resources :favorites, only: [:create, :destroy]
end
この状態で、ターミナルにて、rails routes
を実行します。
Prefix Verb URI Pattern Controller#Action
favorites POST /favorites(.:format) favorites#create
favorite DELETE /favorites/:id(.:format) favorites#destroy
これだとパス(URL)の中に、どのwordに対してお気に入り機能が働いているかを示す情報がありません。
お気に入り機能が働く際には、どのワードに対してのものなのかをパスから判断し、かつコントローラーにその情報を渡したいので、ルーティングのネストを用います。
以下のように記述。
Rails.application.routes.draw do
resources :word do
resources :favorites, only: [:create, :destroy]
end
end
ターミナルにて、rails routes
を実行します。
Prefix Verb URI Pattern Controller#Action
word_favorites POST /words/:word_id/favorites(.:format) favorites#create
word_favorite DELETE /words/:word_id/favorites/:id(.:format) favorites#destroy
パスの:word_id
という部分に記述された値は、パラメーターとして送られます。
このように、ネストを利用すればwordのid情報を含めることができます。
ルーティングをネストさせる一番の理由は、アソシエーション先のレコードのidをparamsに追加してコントローラーに送るところにあると言えます。
この:word_id
の箇所へ、お気に入り機能が働くと結びつくワードのidを記述すると、paramsのなかにword_idというキーでパラメーターが追加され、コントローラーで扱うことができます。
以上。