Nested resources with rails 5.1 form_with

Per this pull request I see that the array should be passed to the form_with model parameter. However, when I put the following:

 <%= form_with(model: [@trip, @activity], local: true) do |f| %> ... <% end %> 

Rails will return - ActionView::Template::Error (undefined method activity_path' for #<#<Class:0x007f80231e3070>:0x007f8023010dd8>):

My routes file looks like this:

  resources :trips do resources :activities end 

The output of rake routes looks like

  trip_activities GET /trips/:trip_id/activities(.:format) activities#index POST /trips/:trip_id/activities(.:format) activities#create new_trip_activity GET /trips/:trip_id/activities/new(.:format) activities#new edit_trip_activity GET /trips/:trip_id/activities/:id/edit(.:format) activities#edit trip_activity GET /trips/:trip_id/activities/:id(.:format) activities#show PATCH /trips/:trip_id/activities/:id(.:format) activities#update PUT /trips/:trip_id/activities/:id(.:format) activities#update DELETE /trips/:trip_id/activities/:id(.:format) activities#destroy trips GET /trips(.:format) trips#index POST /trips(.:format) trips#create new_trip GET /trips/new(.:format) trips#new edit_trip GET /trips/:id/edit(.:format) trips#edit trip GET /trips/:id(.:format) trips#show PATCH /trips/:id(.:format) trips#update PUT /trips/:id(.:format) trips#update DELETE /trips/:id(.:format) trips#destroy 

And my activity_controller.rb is

  before_action :set_activity, only: %i[show update edit destroy] def edit; end def update dates = calculate_datetimes(params[:date_range]) @activity.assign_attributes(name: params[:name], summary: params[:summary], start_datetime: dates[0], end_datetime: dates[1]) if @activity.save flash[:success] = 'Activity successfully updated' redirect_to(@trip) else set_humanized_daterange render :edit end end private def set_activity @activity = Activity.find(params[:id]) end 

tl; dr - how do I configure my form_with for a nested resource, and why do I want to use activity_path for this form of thinking? Ideally, I would like to move this form to partial and use the same form for my #new and #edit actions.

+20
source share
4 answers

Try specifying the model and URL separately:

 form_with(model: @activity, url: [@trip, @activity]) 

According to the documentation, the values โ€‹โ€‹for url โ€œakin to the values โ€‹โ€‹passed to url_for or link_toโ€, so using an array should work.

This also works with shallow nesting since the array is compressed.

+29
source

You just need to add the URL to the route you want to point the form to, i.e. , url: trip_activity_path or whatever path you click:

+4
source

Adding to the maximum answer , if you want to support a shallow attachment, you can also use:

form_with(model: [@trip, @activity])

And change the render on your edit.html.erb to pass nil to trip, for example:

<%= render 'form', trip: nil, activity: @activity %>

and save it by passing the shutdown model in new.html.erb

+3
source

Changing the URL is good, but you can change the model instead, which allows the builder to display the URL and any scope, etc.

 <%= form_with(model: child.new_record? ? [@parent, child] : child, local: true) do |form| %> 

new / edit views: <%= render 'form', child: @child %>

controllers will have to set @parent from the url parameters, which in any case is a convention for nested resources.

0
source

Source: https://habr.com/ru/post/1272861/


All Articles