Search code examples
ruby-on-railsrubyformsruby-on-rails-6nested-resources

Form helper, nested resources without setting the parent resource


If we've models as:

class Book < ApplicationRecord
  has_many :chapters
end

class Chapter < ApplicationRecord
  belongs_to :book
end

with routes:

resources :books do
  resources :chapters
end

and we want to create a form as:

<%= form_with(url: new_book_chapter_url(chapter) do |f| %>

How could we create this kind of form (/books/:id/chapters/new) without setting the book id ?

The example above will throw:

No route matches {:action     => "new",
                  :book_id    => nil,
                  :controller => "chapter"},
missing required keys: [:book_id]

In my case the user set the wished book within the form, and I'd like it to be blank when the form appears


Solution

  • There are several problems here and I don't think you have actually understood the basics of RESTful routing in Rails or what nested routes should be used for.

    If you want to create a chapter without specifying the book in the form action then you shouldn't be using a nested route. Just declare a non-nested route.

    resources :chapters, only: [:create]
    
    <%= form_with(model: chapter) do |f| %>
      <div class="field">
        <%= f.label :book_id, "Select a book" %>
        <%= f.collection_select :book_id, Book.all, :id, :name %>
      </div>
    <% end %>
    

    When creating a resource you POST to the collection path (/chapters) not (/chapters/new). The new and edit actions in Rails are only used to display forms. This applies to both nested and non-nested routes.

    You also should use the model option and just let Rails infer the route from the passed record. url should only be used when you must break the conventions or are using a form without a model.

    See: