##概要
resourcesを多段階ネストさせた時のform_forメソッドの使用方法に関する記事があまりなかったので、備忘録として纏めます。
スポット(Post)ごとに写真(Image)が投稿でき、写真ごとにコメント(Comment)が投稿できる旅行カタログアプリケーションを作成しております。
ビューはHamlで書いております。
作成途中のため、細かいところはご容赦くださいませ。
##ルーティング
routes.rb
resources :posts, only: [:index, :new, :create, :edit, :update] do
resources :images, only: [:index, :new, :create, :show] do
resources :comments, only: [:index, :create]
end
end
##コントローラ
1つ目のネストのimageは下記の通り。
images_controller.rb
class ImagesController < ApplicationController
before_action :set_post
def index
@images = @post.images.includes(:user)
end
def new
@image = Image.new
end
def create
@image = @post.images.new(image_params)
if @image.save
redirect_to post_images_path(@post)
else
@images = @post.images.includes(:user)
render :index
end
end
private
def image_params
params.require(:image).permit(:text, :image).merge(user_id: current_user.id)
end
def set_post
@post = Post.find(params[:post_id])
end
end
2つ目のネストのcommentは下記となる。
PostのIDを定義する必要があることに気付くのに時間がかかりました・・・
comments_controller.rb
class CommentsController < ApplicationController
before_action :set_image
def index
@post = Post.find(params[:post_id])
@comment = Comment.new
@comments = @image.comments.includes(:user)
end
def create
@post = Post.find(params[:post_id])
@comment = @image.comments.new(comment_params)
if @comment.save
redirect_to post_image_comments_path(@post, @image)
else
@comments = @image.comments.includes(:user)
render :index
end
end
private
def comment_params
params.require(:comment).permit(:content).merge(user_id: current_user.id)
end
def set_image
@image = Image.find(params[:image_id])
end
end
##モデル
image.rb
class Image < ApplicationRecord
belongs_to :post
belongs_to :user
has_many :comments
validates :image, presence: true
end
comment.rb
class Comment < ApplicationRecord
belongs_to :post
belongs_to :user
validates :content, presence: true
end
##ビュー
new-image.html.haml
.new-image__form
= form_for [@post, @image] do |f|
= f.label :image, class: 'form__image' do
= icon('fas', 'image', class: 'icon')
= f.file_field :image, class: 'hidden'
.new-image__form__mask
= f.text_field :text, class: 'form__text', placeholder: 'type a caption'
= f.submit 'Send', class: 'form__submit'
new-comment.html.haml
.comments__content__list__form
= form_for [@post, @image, @comment ] do |f|
.comments__content__list__form__new-comment
.comments__content__list__form__new-comment__input-box
= f.text_field :content, class: 'new-comment__input-box__text', placeholder: 'コメントを追加...', inputtype: "text", style:"border:none"
= f.submit 'Send', class: 'new-comment__submit-btn'
2段ネストした場合のform_forの引数は、親、子、孫の関係になるため、post, image, commentの3つを渡しています。
##以上です
間違いあればご指摘お願いいたします!