web-dev-qa-db-ja.com

ネストされたリソースw / Rails 5.1 form_with

この プルリクエストごとに 配列を_form_with_のモデルパラメーターに渡す必要があることがわかります。ただし、以下を提供する場合:

_<%= 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アクションの両方に同じフォームを使用するのが理想的です。

18
colincr

モデルとURLを別々に指定してみてください。

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

ドキュメントによると、urlの値は「url_forまたはlink_toに渡される値と同じ」であるため、配列の使用は機能するはずです。

これは、配列が圧縮されているため、浅いネストでも機能します。

27
max

フォームが指すルートにURLを追加するだけです。つまり、, url: trip_activity_pathまたはヒットしているパスは何でも

4
jfarn23

max answer に追加します。浅いネストをサポートする場合は、次を使用することもできます。

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

そして、次のように、edit.html.erbのレンダリングを変更して、nilをtripに渡します。

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

そして、new.html.erbの旅行モデルを通過させます

3

URLの変更は問題ありませんが、代わりにモデルを変更して、ビルダーがURLやスコープなどを推測できるようにすることができます。

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

新規/編集ビュー:<%= render 'form', child: @child %>

コントローラーは、URLパラメーターから@parentを設定する必要があります。これは、とにかくネストされたリソースの規則です。

0
Matt