ruby-on-railsturbo-rails

Template Error: missing partial bar/foo/_new


I want to display a root page which shows a turbo frame with a form for creating a new object. However the routing doesn't work as I want, because I get the above mentioned error.

routes.rb

namespace :cust do
  resources :customer_dates, only: [:index, :show, :create, :new]
end
root "cust/customer_bookings#index"

/views/cust/customer_bookings/index.html.erb

<div><%= render "main" %></div>

/views/cust/customer_bookings/_main.html.erb

<%= turbo_frame_tag @customer_date do %>
  <%= render new_cust_customer_date_path, customer_date: @customer_date %>
<% end %>

Error

ActionView::Template::Error (Missing partial cust/customer_dates/_new with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby, :jbuilder]}.

And the line causing the error is the one in _main.html.erb with new_cust_customer_date_path. In /views/cust/customer_dates folder I have the views new.html.erb and _form.html.erb


Solution

  • new_cust_customer_date_path is a url helper, you can use it with link_to, button_to, form_with url: etc. render works with your local files, which may or may not match the url path.

    To clarify:

    "localhost:3000/cust/customer_dates/new" # request from the browser
    # bin/rails routes                       # will match one of the routes
    namespace :cust do                       # `/cust` to `module Cust`
      resources :customer_dates,             # `/customer_dates` to `CustomerDatesController`
        only: [:index, :show, :create, :new] # `/new` to `def new`
    end                                      # Cust::CustomerDatesController#new
    def new                                  # controller action
      @customer_date = CustomerDate.new      # do some things
                                             # unless you render something, rails
      # render :new                          # will implicitly `render "#{action_name}"`
    end                                      # in controllers, `render` defaults to
    new.html.erb                             # rendering a template with layout:
                                             # render template: "cust/customer_dates/new", layout: "application"
    

    Inside the views, render defaults to rendering a partial and no layout.

    new_cust_customer_date_path #=> /cust/customer_dates/new
    
    <%= render "/cust/customer_dates/new", customer_date: @customer_date %>
    # which is the same as
    <%= render partial: "/cust/customer_dates/new", locals: { customer_date: @customer_date } %>
    
    # partial is the same as template, but will auto prefix `_` to the filename
    <%= render template: "/cust/customer_dates/_new", locals: { customer_date: @customer_date } %>
    

    Since you don't have _new.html.erb file, you get an error. If you need to render a form, you can do this:

    <%= render "cust/customer_dates/form", customer_date: @customer_date %>
    #                               ^
    #                               form is a partial `_form`
    
    # or render `new.html.erb` as a template (no underscore)
    #                                         v
    <%= render template: "cust/customer_dates/new", locals: { customer_date: @customer_date } %>
    

    Note that "cust/customer_dates/new" is just a path relative to app/views.


    https://guides.rubyonrails.org/layouts_and_rendering.html