web-dev-qa-db-fra.com

Ressources imbriquées avec Rails 5.1 form_with

Per cette requête d'extraction Je peux voir qu'un tableau doit être passé au paramètre de modèle de form_with. Cependant, lorsque je fournis ce qui suit:

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

Les rails vont revenir - ActionView::Template::Error (undefined method activity_path' for #<#<Class:0x007f80231e3070>:0x007f8023010dd8>):

Mon fichier de routes ressemble à:

  resources :trips do
    resources :activities
  end

La sortie de rake routes ressemble à - 

     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

Et mon activities_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 - Comment dois-je configurer mon formulaire avec une ressource imbriquée, et pourquoi ce formulaire pense-t-il que je souhaite utiliser le activity_path? Idéalement, j'aimerais déplacer ce formulaire dans un partiel et utiliser le même formulaire pour mes actions #new et #edit.

12
colincr

Essayez de spécifier le modèle et l’URL séparément:

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

Selon la documentation, les valeurs de url sont "des valeurs semblables à celles transmises à url_for ou link_to", de sorte que l'utilisation d'un tableau devrait fonctionner. 

Pour prendre en charge l’imbrication peu profonde, vous pouvez utiliser une condition comme ceci:

form_with(model: @activity, url: (@activity.new_record? ? [@trip, @activity]: @activity))
21
max

Il vous suffit d’ajouter l’URL à l’itinéraire auquel vous souhaitez que le formulaire pointe, par exemple: , url: trip_activity_path

4
jfarn23

Changer l'URL est acceptable, mais vous pouvez plutôt changer le modèle, ce qui permet au constructeur de déduire l'URL et toute portée, etc.:

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

nouveau/modifier vues: <%= render 'form', child: @child %>

les contrôleurs devront définir @parent à partir des paramètres d'URL, ce qui est de toute façon une convention pour les ressources imbriquées.

0
Matt