Skip to content

rake routes is duplicating api_version routes #50

Closed
sricc opened this Issue Aug 16, 2013 · 4 comments

2 participants

@sricc
sricc commented Aug 16, 2013

I am getting duplicate routes within a rake routes when resources are within an api_version block.

My routes are setup as follows

MyApp::Application.routes.draw do
  root :to => redirect("/signin")

  # Devise
  devise_for :users, :skip => [:sessions]
  as :user do
    get 'signin'     => 'home#index',              :as => :new_user_session
    post 'signin'    => 'devise/sessions#create',  :as => :user_session
    delete 'signout' => 'devise/sessions#destroy', :as => :destroy_user_session
  end

  # API
  api_version(:module => 'api/v1', :header => {:name => 'Accept', :value => "application/vnd.domain.com; version=1"}, :default => true, :defaults => {:format => :json}) do

      get 'things' => 'thing#index'
      resources 'thing', except: :index

  end
end

When I run rake routes this is my output

 Prefix Verb   URI Pattern                    Controller#Action
                root GET    /                              redirect(301, /signin)
       user_password POST   /users/password(.:format)      devise/passwords#create
   new_user_password GET    /users/password/new(.:format)  devise/passwords#new
  edit_user_password GET    /users/password/edit(.:format) devise/passwords#edit
                     PATCH  /users/password(.:format)      devise/passwords#update
                     PUT    /users/password(.:format)      devise/passwords#update
    new_user_session GET    /signin(.:format)              home#index
        user_session POST   /signin(.:format)              devise/sessions#create
destroy_user_session DELETE /signout(.:format)             devise/sessions#destroy
              things GET    /things(.:format)              api/v1/thing#index {:format=>:json}
         thing_index POST   /thing(.:format)               api/v1/thing#create {:format=>:json}
           new_thing GET    /thing/new(.:format)           api/v1/thing#new {:format=>:json}
          edit_thing GET    /thing/:id/edit(.:format)      api/v1/thing#edit {:format=>:json}
               thing GET    /thing/:id(.:format)           api/v1/thing#show {:format=>:json}
                     PATCH  /thing/:id(.:format)           api/v1/thing#update {:format=>:json}
                     PUT    /thing/:id(.:format)           api/v1/thing#update {:format=>:json}
                     DELETE /thing/:id(.:format)           api/v1/thing#destroy {:format=>:json}
                     GET    /things(.:format)              api/v1/thing#index {:format=>:json}
                     POST   /thing(.:format)               api/v1/thing#create {:format=>:json}
                     GET    /thing/new(.:format)           api/v1/thing#new {:format=>:json}
                     GET    /thing/:id/edit(.:format)      api/v1/thing#edit {:format=>:json}
                     GET    /thing/:id(.:format)           api/v1/thing#show {:format=>:json}
                     PATCH  /thing/:id(.:format)           api/v1/thing#update {:format=>:json}
                     PUT    /thing/:id(.:format)           api/v1/thing#update {:format=>:json}
                     DELETE /thing/:id(.:format)           api/v1/thing#destroy {:format=>:json}

As you can see, the first set of routes are:

              things GET    /things(.:format)              api/v1/thing#index {:format=>:json}
         thing_index POST   /thing(.:format)               api/v1/thing#create {:format=>:json}
           new_thing GET    /thing/new(.:format)           api/v1/thing#new {:format=>:json}
          edit_thing GET    /thing/:id/edit(.:format)      api/v1/thing#edit {:format=>:json}
               thing GET    /thing/:id(.:format)           api/v1/thing#show {:format=>:json}
                     PATCH  /thing/:id(.:format)           api/v1/thing#update {:format=>:json}
                     PUT    /thing/:id(.:format)           api/v1/thing#update {:format=>:json}
                     DELETE /thing/:id(.:format)           api/v1/thing#destroy {:format=>:json}

and the second set of routes are:

                     GET    /things(.:format)              api/v1/thing#index {:format=>:json}
                     POST   /thing(.:format)               api/v1/thing#create {:format=>:json}
                     GET    /thing/new(.:format)           api/v1/thing#new {:format=>:json}
                     GET    /thing/:id/edit(.:format)      api/v1/thing#edit {:format=>:json}
                     GET    /thing/:id(.:format)           api/v1/thing#show {:format=>:json}
                     PATCH  /thing/:id(.:format)           api/v1/thing#update {:format=>:json}
                     PUT    /thing/:id(.:format)           api/v1/thing#update {:format=>:json}
                     DELETE /thing/:id(.:format)           api/v1/thing#destroy {:format=>:json}

This doesn't happen if I put the same resource in a namespace or just as a regular route only within api_version.

Am I doing something wrong or is this a bug?

Thanks.

@bploetz
Owner
bploetz commented Aug 16, 2013

It actually looks like the :default => true is causing that. Observe:

 api_version(:module => 'api/v1', :header => {:name => 'Accept', :value => "application/vnd.domain.com; version=1"}, :default => true, :defaults => {:format => :json}) do
    resources :foos
  end
> bundle exec rake routes
  Prefix Verb   URI Pattern              Controller#Action
    foos GET    /foos(.:format)          api/v1/foos#index {:format=>:json}
         POST   /foos(.:format)          api/v1/foos#create {:format=>:json}
 new_foo GET    /foos/new(.:format)      api/v1/foos#new {:format=>:json}
edit_foo GET    /foos/:id/edit(.:format) api/v1/foos#edit {:format=>:json}
     foo GET    /foos/:id(.:format)      api/v1/foos#show {:format=>:json}
         PATCH  /foos/:id(.:format)      api/v1/foos#update {:format=>:json}
         PUT    /foos/:id(.:format)      api/v1/foos#update {:format=>:json}
         DELETE /foos/:id(.:format)      api/v1/foos#destroy {:format=>:json}
         GET    /foos(.:format)          api/v1/foos#index {:format=>:json}
         POST   /foos(.:format)          api/v1/foos#create {:format=>:json}
         GET    /foos/new(.:format)      api/v1/foos#new {:format=>:json}
         GET    /foos/:id/edit(.:format) api/v1/foos#edit {:format=>:json}
         GET    /foos/:id(.:format)      api/v1/foos#show {:format=>:json}
         PATCH  /foos/:id(.:format)      api/v1/foos#update {:format=>:json}
         PUT    /foos/:id(.:format)      api/v1/foos#update {:format=>:json}
         DELETE /foos/:id(.:format)      api/v1/foos#destroy {:format=>:json}
 api_version(:module => 'api/v1', :header => {:name => 'Accept', :value => "application/vnd.domain.com; version=1"}, :defaults => {:format => :json}) do                                                                                                                                           
    resources :foos
  end
> bundle exec rake routes
  Prefix Verb   URI Pattern              Controller#Action
    foos GET    /foos(.:format)          api/v1/foos#index {:format=>:json}
         POST   /foos(.:format)          api/v1/foos#create {:format=>:json}
 new_foo GET    /foos/new(.:format)      api/v1/foos#new {:format=>:json}
edit_foo GET    /foos/:id/edit(.:format) api/v1/foos#edit {:format=>:json}
     foo GET    /foos/:id(.:format)      api/v1/foos#show {:format=>:json}
         PATCH  /foos/:id(.:format)      api/v1/foos#update {:format=>:json}
         PUT    /foos/:id(.:format)      api/v1/foos#update {:format=>:json}
         DELETE /foos/:id(.:format)      api/v1/foos#destroy {:format=>:json}

The way defaulting works is that it actually puts in another scope into your routes to handle the case when no version is requested:

https://github.com/bploetz/versionist/blob/master/lib/versionist/routing.rb#L64

Unfortunately rake routes doesn't show you the advanced constraints info (http://guides.rubyonrails.org/routing.html#advanced-constraints) which is where versionist hooks in to do it's thing. If it did, you'd see one is the actual version handler, the other is the default handler.

@sricc
sricc commented Aug 16, 2013

Ah, ok, I see. Maybe it would be a good idea to make a note of this in the README docs.

Thanks!

@bploetz
Owner
bploetz commented Aug 16, 2013

Yeah I will note this in the README. Frankly I never noticed it until you pointed it out. :-) Thanks!

@bploetz bploetz closed this Aug 16, 2013
@sricc
sricc commented Aug 16, 2013

Glad to help!

@bploetz bploetz pushed a commit that referenced this issue Aug 16, 2013
Brian Ploetz Issue #50: Clarify behavior of default version and rake routes a5abdcc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.