作成中のアプリケーションにて苦戦した、ルーティングのネストをした際のparamsの取得についてアウトプットを兼ねて書いていきます。
機能としては、ある店舗に対するコメントができる、というよくあるクチコミサイトのような感じです。
コメントは店舗詳細ページ内で投稿ができ、投稿が成功すると詳細ページにリダイレクトされます。
ルーティングは、
resources :stores do
resources :comments, only: :create
end
StoreモデルとCommentモデルが親子関係になっているため上記記述になっています。
次にstoresコントローラー内ですが、
def show
@comment = Comment.new
@store = Store.find(params[:id])
@comments = @store.comments.includes(:user)
end
2行目でCommentモデルの空のインスタンスを生成しました。
3行目ではStoreモデルから店舗のidを取得する記述をしています。
4行目では、店舗詳細ページ(@storeが含んだid)に紐づく投稿されたコメント(comments)とそれを投稿したユーザー(:uesr)全ての情報を取得しています。
N+1問題を回避するため、allではなくincrudesを使っています。
次はcommentsコントローラー内です。ここが詰まったところでした。
def create
@store = Store.find(params[:store_id]) #店舗idを取得しています
@comment = Comment.new(comment_params) #空のインスタンスにcomment_paramsメソッドで取得したparamsの情報を入れています
if @comment.save
redirect_to store_path(@store) #保存ができた場合、詳細ページにリダイレクト
else
@comments = @store.comments.includes(:user) #保存ができなかった場合、詳細ページがレンダリングされます。
render "stores#show"
end
end
private
def comment_params
params.require(:comment).permit(:content).merge(user_id: current_user.id, store_id: params[:store_id])
end
createアクション内の上から2行目と、下から4行目のprivateメソッド内のcomment_paramsメソッドでparams[:store_id]としています。
idを取ってくるだけならparams[:id]で良さそうです…がこれだと取得できません。
rails routesコマンドをすると理由がわかりました。
store_comments POST /stores/:store_id/comments(.:format) comments#create
:idではなく:store_idとなっています。ここが私的に大きなポイントでした。
結論:rails routesはすごい