Вложенные ресурсы с рельсами 5.1 form_with

Per this pull request Я вижу, что массив должен быть передан в параметр form_with model. Однако, когда я поставлю следующее:

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

Rails вернутся - ActionView::Template::Error (undefined method activity_path' for #<#<Class:0x007f80231e3070>:0x007f8023010dd8>):

Мой файл маршрутов выглядит так:

  resources :trips do
    resources :activities
  end

Вывод rake routes выглядит как

     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

И мой activity_controller.rb -

  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 - как мне настроить свой form_with для вложенного ресурса, и почему эта форма мышления я хочу использовать activity_path? В идеале я хотел бы переместить эту форму в частичную и использовать ту же форму для моих #new и #edit действий.

Ответ 1

Попробуйте указать модель и URL-адрес отдельно:

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

В соответствии с документацией, значения для url "сродни значениям, переданным в url_for или link_to", поэтому использование массива должно работать.

Это также работает с неглубоким вложением, так как массив сжат.

Ответ 2

Вам просто нужно добавить URL-адрес к маршруту, на который хотите указать форму, т.е. , url: trip_activity_path или независимо от того, какой путь вы нажимаете:

Ответ 3

Добавив в максимальный ответ, если вы хотите поддерживать мелкое вложение, вы также можете использовать:

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

И измените рендер на вашем edit.html.erb, чтобы передать nil в trip, например:

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

и сохраните его, передав модель отключения в файле new.html.erb

Ответ 4

Изменение URL - это хорошо, но вы можете вместо этого изменить модель, которая позволяет строителю выводить URL и любую область видимости и т. Д.:

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

новые/редактировать представления: <%= render 'form', child: @child %>

контроллеры должны будут установить @parent из параметров url, что в любом случае является соглашением для вложенных ресурсов.