Add new view to a controller in Rails

Viewed 9863

I have a controller, clients_controller, with corresponding index, show, edit, delete, new & form views. Is there a way to create a new view like clients/prospects.html.erb that acts the same way as clients/index.html.erb, except is routed at clients/prospects/?

I've tried this:

match '/clients/prospects' => 'clients#prospects'

And some other things in routes.rb, but of course get the error "Couldn't find Client with id=prospects".

The goal here is basically to have a prospects view and a clients view, and by simply switching the hidden field to a 1, it (in the user's mind) turns a prospect into a client (it's a CRM-like app).

3 Answers

There's a couple of things you need to do. First you need to put the your custom route before any generic route. Otherwise Rails assumes the word "prospects" is an id for the show action. Example:

get '/clients/prospects' => 'clients#prospects' # or match for older Rails versions
resources :clients

Also you need to copy / paste the index method in your ClientsController and name it prospects. Example:

class ClientsController < ApplicationController
  def index
    @clients = Client.where(prospect: false)
  end

  def prospects
    @prospects = Client.where(prospect: true)
  end
end

Lastly, you need to copy the index.html.erb view and name the copy prospects.html.erb. In the example above you would have to work with the @prospects instance variable.

Create a new action in clients controller named prospects. And then define a collection route in routes.rb for it as either resource full way. Or u directly use match as you were doing.

What you're doing is not wrong (although I'd change match to get, otherwise POST and DELETE requests to that url will also render your prospects view). Presumably you have

resources :clients

in your routes file? If so, what you have will probably work if you just move the line you quoted above the resources declaration -- the problem is that /clients/prospects matches the show route for the clients resource, so if it's defined first then that's the route that gets matched.

However, there's a more idiomatic way to define this route

resources :clients do
  collection do
    get :prospects
  end
end

See Rails Routing documentation for more

Also see migu's answer for what else needs to be done once the url is being routed correctly (though there are other things you can do -- if you the two views are similar enough, you can reuse the view template, for example).

Related