Harfangk
Harfangk

Reputation: 843

Rails collection routing connects to :show action

Here's my route.rb file:

namespace :api, defaults: { format: 'json' } do
  namespace :v1 do
    resources :projects, :only => [:index, :create, :update, :destroy, :show] do
      resources :events, shallow: true
      resources :comments, shallow: true
      resources :posts, shallow: true
      resources :users, shallow: true
      resources :project_participations, shallow: true
    end

    resources :users, :only => [:show, :index] do
      collection do
        get :search
        post :register_push_receiver_device_id
        delete :deregister_push_receiver_device_id
      end
    end
  end
end

When I make request to /api/v1/users/search, this is how the server responds.

Started GET "/api/v1/users/search?search_string=jason" for 127.0.0.1 at 2016-05-13 18:11:02 +0900
Processing by API::V1::UsersController#show as JSON
  Parameters: {"search_string"=>"jason", "id"=>"search", "user"=>{}}
  User Load (3.1ms)  SELECT  "users".* FROM "users"  WHERE "users"."email" = 'EMAIL'  ORDER BY "users"."id" ASC LIMIT 1
  User Load (4.7ms)  SELECT  "users".* FROM "users"  WHERE "users"."email" = 'EMAIL' AND "users"."authentication_token" = 'TOKEN'  ORDER BY "users"."id" ASC LIMIT 1
  User Load (2.7ms)  SELECT  "users".* FROM "users"  WHERE "users"."id" = 0 LIMIT 1
Filter chain halted as :set_user rendered or redirected
Completed 404 Not Found in 70ms (Views: 0.4ms | ActiveRecord: 17.9ms)

As you can see, the request is routed to :show action with 'search' as the id, leading to error.

Interestingly, the request functions fine when I switch the order of projects resources with users resources in the route.rb file.

namespace :api, defaults: { format: 'json' } do
  namespace :v1 do
    resources :users, :only => [:show, :index] do
      collection do
        get :search
        post :register_push_receiver_device_id
        delete :deregister_push_receiver_device_id
      end
    end

    resources :projects, :only => [:index, :create, :update, :destroy, :show] do
      resources :events, shallow: true
      resources :comments, shallow: true
      resources :posts, shallow: true
      resources :users, shallow: true
      resources :project_participations, shallow: true
    end
  end
end

In this case, the request is handled correctly.

Started GET "/api/v1/users/search?search_string=jason" for 127.0.0.1 at 2016-05-13 18:21:14 +0900
Processing by API::V1::UsersController#search as JSON
  Parameters: {"search_string"=>"jason", "user"=>{}}
  User Load (2.9ms)  SELECT  "users".* FROM "users"  WHERE "users"."email" = 'EMAIL'  ORDER BY "users"."id" ASC LIMIT 1
  User Load (2.5ms)  SELECT  "users".* FROM "users"  WHERE "users"."email" = 'EMAIL' AND "users"."authentication_token" = 'TOKEN'  ORDER BY "users"."id" ASC LIMIT 1
  User Load (80.6ms)  SELECT "users".* FROM "users"  WHERE "users"."status" = 'member' AND (name LIKE '%jason%')  ORDER BY "users"."name" ASC
  Rendered api/v1/users/search.json.jbuilder (86.4ms)
Completed 200 OK in 248ms (Views: 90.0ms | ActiveRecord: 99.7ms)

I've read through Rails routing docs but I just can't understand this behavior. Can someone please explain why this is happening??

Upvotes: 0

Views: 162

Answers (2)

Pavan
Pavan

Reputation: 33542

:users scoped under :projects should not be affecting :users itself!

No, when you run rake routes, you will see the below route.

user GET  /users/:id(.:format)  users#show

This is because you have shallow :true for the resources :users. This gives you some non-nested routes which includes the show route as well(which is the one currently troubling you with that issue). so the order matters here.

Upvotes: 1

Vasfed
Vasfed

Reputation: 18454

This is because you have a shallow route for projects/users, it defines /api/v1/users/:id routes.

See your rake routes

Upvotes: 1

Related Questions