19

I have a controller with a number of actions:

class TestsController < ApplicationController
   def find
   end

   def break
   end

   def turn
   end
end

When I add it to my routes.rb file like so:

resources :tests

and execute the rake routes task I see the following extra rounds:

    tests GET    /tests(.:format)          tests#index
          POST   /tests(.:format)          tests#create
 new_test GET    /tests/new(.:format)      tests#new
edit_test GET    /tests/:id/edit(.:format) tests#edit
     test GET    /tests/:id(.:format)      tests#show
          PUT    /tests/:id(.:format)      tests#update
          DELETE /tests/:id(.:format)      tests#destroy

Obviously my controller doesn't have the above actions. So how do I tell Rails to avoid generating/expecting those routes?

Roman
  • 10,309
  • 17
  • 66
  • 101

3 Answers3

49

Just add an answer for future, simple ways of route without CRUD :

resources :tests, only: [] do 
  collection do 
    get 'find'
    match 'break'
    match 'turn'
  end 
end

# output of rake routes

find_tests GET /tests/find(.:format)  tests#find
break_tests     /tests/break(.:format) tests#break
turn_tests     /tests/turn(.:format)  tests#turn

or use namespace instead of resources

namespace :tests do
  get 'find'
  match 'break'
  match 'turn'
end

# output of rake routes

tests_find GET /tests/find(.:format)  tests#find
tests_break     /tests/break(.:format) tests#break
tests_turn     /tests/turn(.:format)  tests#turn

for Rails 4. (cause match method has been deprecated in rails 4.x or latest)

resources :tests, only: [] do 
  collection do 
    get 'find'
    get 'break'
    get 'turn'
  end 
end

use namespace

namespace :tests do
  get 'find'
  get 'break'
  get 'turn'
end
rails_id
  • 8,120
  • 4
  • 46
  • 84
11

You can specify actions you want to route like this:

resources :tests, except: [:new, :create, :edit, :update, :destroy] do 
  collection do 
    get 'find'
    get 'break'
    get 'turn'
  end 
end
rails_id
  • 8,120
  • 4
  • 46
  • 84
a.s.t.r.o
  • 3,261
  • 5
  • 34
  • 41
  • This still generates routes for `new`, `create`, `edit`, `update` etc. He should have a look at [non-resourceful routes](http://guides.rubyonrails.org/routing.html#non-resourceful-routes). – Mischa Jul 04 '13 at 08:37
  • It can be avoided simply using the `resources :tests, except: [:new, :create, :edit]` etc. if needed (wasn't asked for so I didn't include it to begin with). – a.s.t.r.o Jul 04 '13 at 08:39
  • That is a very strange workaround: generate all the resourceful routes, except all the resourceful routes. – Mischa Jul 04 '13 at 08:40
  • Mischa, the OP asked for something else, he focused his question on this particular issue, it doesn't mean he doesn't use other actions. – a.s.t.r.o Jul 04 '13 at 08:42
  • No, he is **exactly** asking for that: "Obviously my controller doesn't have the above actions. So how do I tell Rails to avoid generating/expecting those routes?" He doesn't want the general CRUD routes. There is no use for `resources :tests` here. – Mischa Jul 04 '13 at 08:44
  • You are right, I didn't saw the "avoid generating" part. I stand corrected :) – a.s.t.r.o Jul 04 '13 at 08:45
  • If you're going to do this, at least use `:only` instead of `:except`. @anonymousxxx, you forgot `index` and `show`. – Mischa Jul 04 '13 at 08:52
  • @Mischa IMHO, yes this is a strange workaround, but still able to work, as the time when we will be adding one of the curd (e.g destroy) we do not need to add resources but simply remove it from the "except". oh I forgot that – rails_id Jul 04 '13 at 08:52
  • @Mischa, I want rails to generate route methods like new_test_find which I will get by using `resources` and `collections`. If you know of a better way please share :) – Roman Jul 04 '13 at 11:06
  • 2
    @Arman `get '/tests/find', :to => 'tests#find', :as => :test_find`. With that you can use `test_find_path` and `test_find_url`. – Mischa Jul 04 '13 at 11:10
  • Okay, that's better. Thanks @Mischa – Roman Jul 05 '13 at 02:22
1

If you don't want the restful routes, don't use resources, specify each path and action on it's own.

get '/tests/find' => 'tests#find'
post '/tests/break' => 'tests#break'
post '/tests/turn' => 'tests#turn'

And you specify params like so:

post '/tests/add/:id' => 'tests#add'
Chris Cherry
  • 28,118
  • 6
  • 68
  • 71