tfantina
tfantina

Reputation: 804

Rails has_many through association delete path

I have a place model and a user model and a user_place model, user_place belongs to user and place both. Traditional has_many through association.

I have a page where you can view the users associated with a place. My routes look like:

  resources :places do
    resources :user_places
  end

which generates these routes:

place_user_places GET    /places/:place_id/user_places(.:format)                                                  user_places#index
                                      POST   /places/:place_id/user_places(.:format)                                                  user_places#create
                 new_place_user_place GET    /places/:place_id/user_places/new(.:format)                                              user_places#new
                edit_place_user_place GET    /places/:place_id/user_places/:id/edit(.:format)                                         user_places#edit
                     place_user_place GET    /places/:place_id/user_places/:id(.:format)                                              user_places#show
                                      PATCH  /places/:place_id/user_places/:id(.:format)                                              user_places#update
                                      PUT    /places/:place_id/user_places/:id(.:format)                                              user_places#update
                                      DELETE /places/:place_id/user_places/:id(.:format)           

I don't love this but I'm ok with it for now.

But whenever I try to delete a user_place I have all sorts of issues.

<%= link_to "delete", place_user_place_url(place_id: @user_place.place_id, id: @user_place.id), method: 'delete' %>

No route matches {:action=>"show", :controller=>"user_places", :id=>nil, :place_id=>2}, possible unmatched constraints: [:id]

I had this working previously with slightly different routes and an actual form:

  resources :places do
    resources :user_places, as: 'user', only: %i[index create new]
    delete 'remove_user', to: 'user_places#remove_user'
  end

            <% if user != current_user %>
              <%= form_with model: @user_place, url: place_remove_user_path(@place.id), method: 'delete' do |form| %>
                <%= form.hidden_field :user_id, value: user.id %>
                <%= form.hidden_field :place_id, value: @place.id %>
                <%= form.submit  "delete" %>
              <% end %>
            <% end %>

But this feels hacky, I don't think I should need a specific form, and this was leading the form to be submitted with javascript which I don't want.

Upvotes: 0

Views: 131

Answers (1)

Thomas Van Holder
Thomas Van Holder

Reputation: 1507

What might be a solution is to use shallow nesting in the routes (shallow: true).

resources :places do
 resources :user_places, shallow: true
end

Make sure to run rails routes again. The delete method of a user_place will no longer be nested.

You can then simply delete the user_place passing a single variable (an instance of a user place, @user_place). There is no need to set the id (place_id or id) as Rails is smart enough to handle that. Just passing an instance variable is enough for the delete method to find the corresponding record.

<%= link_to "delete", user_place_url(@user_place), method: 'delete' %>

Upvotes: 1

Related Questions