状況
以下のようにresourcesメソッドを使って、usersの中にpostsをネストするようなルーティングを書いた。
Rails.application.routes.draw do
root 'home#show'
resources :users, only: [:show] do
resources :posts, only: [:index, :new, :create, :destroy]
end
end
postsコントローラーは以下のように書いた。
class PostsController < ApplicationController
before_action :authenticate_user!, only: [:new, :create, :destroy]
def index
@user = User.find(params[:user_id])
@posts = @user.posts
end
def new
@post = Post.new
end
def create
@post = current_user.posts.build(post_params)
if @post.save
redirect_to user_posts_path
else
render action: :new
end
end
def destroy
end
private
def post_params
params.require(:post).permit(:title, :content)
end
end
また、postの新規作成用のviewは以下のコードを書いた。
NEW Posts
<%= form_with(model: @post, local: true) do |f| %>
<%= f.text_field :title %>
<%= f.text_area :content, placeholder: "Compose new post..." %>
<%= f.submit "Post" %>
<% end %>
その結果、postの新規作成画面に遷移した際に以下のようなエラーが表示された。
NoMethodError in Posts#new
undefined method `posts_path' for #<ActionView::Base:0x00000000011878>
対処法
viewのform_withについて以下のようにurl: user_posts_path
とパスを追記する。
NEW Posts
<!-- url: user_posts_pathを追記↓ ---!>
<%= form_with(model: Post.new, url: user_posts_path, local: true) do |f| %>
<%= f.text_field :title %>
<%= f.text_area :content, placeholder: "Compose new post..." %>
<%= f.submit "Post" %>
<% end %>
原因
railsのformメソッドはデータを送信(POSTリクエスト)しデータを新規作成する際に、送信する先のパス(URL)が指定されていなければ、よきにはからってくれる。
すなわち今回のケースでは@post
というモデルが指定されているため、Railsは posts_path
というURLを照会しようと試みた。
しかし、冒頭で定義しているように、postsリソースへのルーティングはusersリソースへのルーティングにネストされている。
従って、postsリソースへのURLはposts_path
ではなく、user_posts_path
となっているので、これを指定しなくてはならない。
(このあたりの確認については localhost/rails/infoにアクセスするとルーティングの一覧を取得できる。)