Reputation: 53
I have two controllers: VendorsController and ServicesController. Vendors have services, and thus I've created nested routes:
#config/routes.rb
Rails.application.routes.draw do
devise_for :users
root "static_pages#index"
get 'start', to: 'static_pages#start'
resources :vendors do
resources :services
end
end
Services are listed on the vendor show page, and thus I want the user who owns the Vendor page to be able to delete a service (all from the vendor show page). Here is my code for this in the services controller:
#services_controller.rb
class ServicesController < ApplicationController
before_action :authenticate_user!
# some more code
def destroy
@vendor = Vendor.find_by_id(params[:vendor_id])
@service = Service.find_by_id(params[:id])
if @service.user == current_user
@service.destroy
redirect_to vendor_path(@vendor), notice: "The service has been deleted."
else
return render text: 'Not Allowed', status: :forbidden
end
end
end
And in vendor/show.html.erb:
<% current_vendor.services.each do |service| %>
<% if current_vendor.user == current_user %>
<%= link_to "Edit Service", edit_vendor_service_path(service), class: 'btn btn-primary float-right'%>
<%= link_to "Delete Service", vendor_service_path(current_vendor), method: :delete, data: {confirm: 'Are you sure? This action cannot be reversed.'}, class: 'btn btn-danger float-right'%>
<% end %>
<% end %>
Note that current_vendor is a helper method. The problem is that this code passes in my rspec test suite, but in practice, I get the error "NoMethodError in ServicesController#destroy. undefined method `user' for nil:NilClass". After fiddling using pry, I realize the only way I could get it to work in practice is through changing the destroy method in my Services controller to this:
def destroy
@vendor = Vendor.find_by_id(params[:id])
@service = Service.find_by_id(params[:vendor_id])
if @service.user == current_user
@service.destroy
redirect_to vendor_path(@vendor), notice: "The service has been deleted."
else
return render text: 'Not Allowed', status: :forbidden
end
end
Once I do this, of course my rspec tests fail. This obviously doesn't make sense but I cannot figure out where I'm going wrong. Can anyone point out my mistake?
Upvotes: 0
Views: 50
Reputation: 5609
You need the nested params of service
in your destroy path :
<%= link_to "Delete Service", vendor_service_path(current_vendor, service), method: :delete %>
Your first version of destroy
method should work this way.
Upvotes: 1