user3735114
user3735114

Reputation: 41

Can't find suitable controller action to render view

I'm trying to do this:

List of Counties

County 1 (links to list of locations within County 1 County 2 (links to list of locations within County 2 etc

List of Locations within County 1

Location 1 (links to location page Location 2 etc

My routes are as follows:

Rails.application.routes.draw do


 resources :counties do
   resources :locations
 end


 root 'home#index'
 get "/:county_name_with_prefix" => "counties#show_by_name" 
 get "/:location_name_with_prefix" => "locations#show_by_name"


end

My CountiesController is this:

class CountiesController < ApplicationController
  before_filter :extract_county_name, :only => [:show_by_name]
  **before_filter :extract_location_name, :only => [:show_by_name]**

   def index
      @counties = County.all
      @locations = Location.all

   end

   def show
      @county = County.find(params[:id])
      @locations = Location.all

   end 

   def show_by_name
      @county = County.find_by_name(@county_name)
      @locations = Location.all
      render :show
   end

   private
   def extract_county_name
     @county_name = params[:county_name_with_prefix].gsub(County::ROUTE_PREFIX,"").gsub("-", " ").strip
   end 

   **private
   def extract_location_name
     @location_name = params[:location_name_with_prefix].gsub(Location::ROUTE_PREFIX,"").gsub("-", " ").strip
   end** 


end

Counties index view is this:

<p>List of all counties</p>

<ul>
  <% @counties.each do |county| %>
      <li><%= link_to "Locations in #{county.name}", generate_county_url_with_prefix(county) %></li>
  <% end %>
</ul>

Counties Show view is this:

<h1>Domestic Cleaning Services in <%= @county.name %></h1>

<ul>
<% @locations.each do |location|%>
<li><%= link_to "#{location.name}"**,generate_location_url_with_prefix(location) %></li>**
<%end%>

</ul>

I can get this to work if I remove the code between the **stars**. However, what I can't figure out is how to get the list of locations to link to each individual location page - my attempts to do this are shown in the **code marked like this**. The database tables are definitely set up ok in terms of relationships/data. Any ideas massively welcomed...

LocationsController:

class LocationsController < ApplicationController
  before_filter :extract_location_name, :only => [:show_by_name]

   def index
      @location = Location.all
   end


   def show
      @location = Location.find(params[:id])

   end 

   def show_by_name
      @location = Location.find_by_name(@location_name)
      render :show
   end

   private
   def extract_location_name
     @location_name = params[:location_name_with_prefix].gsub(Location::ROUTE_PREFIX,"").gsub("-", " ").strip
   end      
end

end

Upvotes: 0

Views: 314

Answers (2)

engineersmnky
engineersmnky

Reputation: 29328

Right now you have overlapping routes

get "/:county_name_with_prefix" => "counties#show_by_name" 
get "/:location_name_with_prefix" => "locations#show_by_name"

These are ambiguous and thus the second will overwrite the first causing all of them to route to locations#show_by_name.

This happens because there is no way for Rails to distinguish /county_name_here from /location_name_here. Does that make sense?

Also there is no need to create a method to generate the route when you can create a named_route using as: this will generate a method for routing using the as name plus _path. e.g. as: :hello will create a method for hello_path.

I would recommend something like

get "/counties/:county_name_with_prefix", to: "counties#show_by_name", as: :county_by_name
get "/locations/:location_name_with_prefix", to: "locations#show_by_name", as: :location_by_name

Then in your view you can use

<ul>
    <% @locations.each do |location|%>
        <li><%= link_to location.name,location_by_name_path(location_name_with_prefix: location.name) %></li>
    <%end%>
</ul>

This will generate routes like /locations/location_name_here in the links so that they work appropriately.

You could however also scope these inside your resources like so:

resources :counties do
  get '/:county_name_with_prefix, to: 'counties#show_by_name', as: :by_name
  resources :locations do
    get '/:location_name_by_prefix', to: 'locations#show_by_name', as: :by_name
  end
end

This will generate routes like

county_by_name          GET /counties/:county_name_with_prefix                 counties#show_by_name
county_location_by_name GET /counties/:id/locations/:location_name_with_prefix locations#show_by_name

Although all of this seems unnecessary when you could just generate links like this using default routing for nested resources. e.g.

<li><%= link_to location.name,county_location_path(location) %></li>

This is because your nested resources have already created this route looking like

county_location  GET  /counties/:county_id/locations/:id locations#show

Which will call :county_id and :id on location and route to something like

/counties/1/locations/12

Upvotes: 1

user934801
user934801

Reputation: 1139

have you already tried something like this?

<%= link_to location.name, county_location_path(@county, location) %>

Upvotes: 0

Related Questions