LoginSignup
0
0

More than 1 year has passed since last update.

お気に入り機能とルーティングのネストについて

Last updated at Posted at 2021-04-13

前提

Railsにて、単語帳アプリを作成しました。
登録される単語をWordモデルとし、お気に入り機能を実装するため、Wordモデルと紐づくFavoriteモデルがあり、以下のようなアソシエーションが組まれています。

app/model/word.rb
class Word < ApplicationRecord
  has_many :favorites, dependent: :destroy
end
app/model/favorite.rb
class Favorite < ApplicationRecord
  belongs_to :word
end

dependent: :destroyで、親モデルが削除されたときは、それに紐付いている子モデルも削除されるように設定。

単語をお気に入りに追加もしくはお気に入りから外す際には、以下のアクションが働きます。

app/controllers/favorites_controller.rb
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

予定している動きとしては、以下の通りです。

  1. 「お気に入りに追加」ボタンを押すと、その単語の情報がFavoritesControllerにパラメーターとして送られてくる。
    (params(送られてきたパラメーターをハッシュのような構造で格納したもの)によって、設定したルーティングのURLに含まれているword_idがFavoritesコントローラーのcreateアクションへ渡される)
  2. before_actionにより、コントローラで定義されたアクション(今回の場合、createアクション)が実行される前に、set_wordアクションが実行され、findメソッドを使用し引数で指定したidのレコードを取得し、インスタンス変数@wordに代入。
    (引数では、送られてきたパラメーターに含まれるwordのid情報をparams[:キー名]で取り出している)
  3. createアクションが実行され、word_idには、パラメーターとして送られてきたwordのidを値に持つインスタンス(お気に入り)を生成し、インスタンス変数@favorieに代入。

この動きを実現させるために、上記のリスト1に関わる、「wordのid情報をパラメーターとしてURLに含める」という作業が必要になります。その上で、コントローラーがその情報を受け取り、アクションが実行され、お気に入りインスタンスが生成されるからです。この場合、ルーティングのネストを意識しなければなりません。

ルーティングのネスト

ネストとは入子構造のこと。
まず、ネストを意識せずにルーティングを記述すると以下の通り。

config/routes.rb
  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に対してお気に入り機能が働いているかを示す情報がありません。
お気に入り機能が働く際には、どのワードに対してのものなのかをパスから判断し、かつコントローラーにその情報を渡したいので、ルーティングのネストを用います。
以下のように記述。

config/routes.rb
  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というキーでパラメーターが追加され、コントローラーで扱うことができます。

以上。

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