The action 'destroy' could not be found for ListingsController

957 Views Asked by At

UPDATE - I'VE NOW SOLVED THIS PROBLEM - I created a partial for the each Course item and rendered them from the main listing view. Thanks for all your help, I'm not really sure why it worked but it did END OF UPDATE

Apologies if this looks like a repeat posting but I've tried applying solutions to similar questions and they haven't worked, I'm stuck! Any suggestions welcomed, thank you.

Problem I have a 'Courses' model which belongs to a 'Listings' model. The courses are created and deleted on a page belonging to Listing i.e. "/listing/2/courses"

Error Message

No route matches [DELETE] "/listings/2/courses" 

Courses Controller def destroy detail

class CoursesController < ApplicationController

  before_action :authenticate_user!, except: [:show]
  before_action :set_listing
  before_action :set_course, except: [:index, :new, :create]

  def destroy
    @course = @listing.courses.find(params[:id])
    @course.destroy
    flash[:notice] = "Course deleted!"
    redirect_back(fallback_location: request.referer)
  end

  private

  def set_course
    @listing = Listing.find(params[:listing_id])
    @course = Course.find(params[:id])
  end

  def set_listing
    @listing = Listing.find(params[:listing_id])
  end

  def course_params
    params.require(:course).permit(:name, :curriculum_type, :summary, :address, :course_places, :start_date, :finish_date, :price)
  end

end

listing/listingID/courses page detail

<%= @listing.courses.each do |f| %>
  <div class="jumbotron">
    <ul>
    <li>Name = <%= f.name %></li>
    <li>Type of course = <%= f.curriculum_type %></li>
    <li>Number of places = <%= f.course_places %></li>
    <li>Start Date = <%= f.start_date %></li>
    <li>Finish Date = <%= f.finish_date %></li>
    <li>Price (£) = <%= f.price %></li>
    <%= link_to "Delete Course", listing_courses_path(@listing, @course), method: :delete %>
    </ul>
  </div>
<% end %>

Routes.rb detail

resources :users, only: [:show]
  resources :listings, except: [:edit] do
    member do
      get 'listing'
      get 'pricing'
      get 'description'
      get 'photo_upload'
      get 'amenities'
      get 'location'
      get 'courses'
    end
        resources :courses, except: [:edit] do
          member do
            get 'listing'
            get 'pricing'
            get 'description'
            get 'photo_upload'
            get 'amenities'
            get 'location'
        end
    end
  end
3

There are 3 best solutions below

3
dARKaRK1002 On

By default, destroy method expects an ID as it's a member route. You are using listing/listingID/courses route without an ID. For that you need to define listing and/or courses as singular resources (read this) like:

resource :courses do
:
end

as described in this answer or make destroy a collection route like so:

resources :courses, except: [:edit] do
  delete :destroy, on: :collection
  :
  rest...
end

Try and see if this works.

By the way, this looks a bit redundant as you are iterating over each @listing.courses and calling courses#destroy where you are destroying all the courses of @listing anyhow. So, why do @listing.courses.each in the first place. You should have either used a listing#destroy_courses method or remove @listing.courses.each iteration.

1
raj_acharya On
<%= link_to listing_course_path(@listing,f), :method => :delete, :data => { :confirm => 'Are you sure?' } %>

or try

  <%= link_to listing_course_path(@listing,id: f.try(:id)), :method => :delete, :data => { :confirm => 'Are you sure?' } %>

route.rb

 resources :listings do
      resources :courses
 end
2
Shahzad Tariq On

Update path in link_to to listing_course_path(@listing, @course) from listing_courses_path(@listing, @course)

<%= link_to "Delete Course", listing_course_path(@listing, f), method: :delete %>