nested namespace route going to wrong controller

2019-03-02 11:43发布

问题:

Using Rails 3.0.7, I'm creating an API for our app, and I have this setup:

routes.rb

  namespace :api do
    namespace :v1 do
      match "connect" => "users#login", :via => :post
      match "disconnect" => "users#logout", :via => :post
      resources :users
      match "users/:id/foos" => "foos#list", :via => :get
      match "users/:id" => "users#update", :via => :put
      match "foos/:id/bars" => "bars#list_by_foo", :via => :get
      match "foos/:id" => "foos#show", :via => :get, :constraints => { :id => /\d+/ }
      match "bars/:id" => "bars#show", :via => :get
    end
  end

  # other routes here e.g.
  match "users/find" => "users#find_by_name", :via => :get
  match "users" => "users#create", :via => :post

And then I have my regular app/controllers/application_controller.rb and app/controllers/users_controller.rb files as well as my app/controllers/api/v1/application_controller.rb and app/controllers/api/v1/users_controller.rb files that are defined like the following:

class Api::V1::ApplicationController < ApplicationController
  before_filter :verify_access

  def verify_access
    # some code here
  end
end

class Api::V1::UsersController < Api::V1::ApplicationController
  skip_before_filter, :except => [:show, :update, :delete]
end

And before everything seemed to be working right until I overrode a method that is shared by both UsersController and Api::V1::UsersController -- and now it seems like everything is pointing to UsersController even though I'm accessing through the api/v1/users route.

I'm at my wit's end trying to figure it out. Any suggestions? Thanks. PS - feel free to comment with whatever conventions I'm ignoring that I shouldn't be or other things I might have messed up :)

回答1:

skip_before_filter also general takes a symbol parameter for the before filter than you wish to skip. Controller names should not have to be unique as long as the proper scoping/namespacing is applied.

example

  • api/users_controller
  • admin/users_controller
  • users_controller

then the code per controller

class Api::V1::UsersController < Api::V1::BaseController
end

class Admin:UsersController < Admin::BaseController
end

class UsersController < ApplicationController
end

Then the routes

MyApp::Application.routes.draw do

scope :module => "api" do
  namespace :v1 do
    resources :users
  end
end

namespace :admin do
  resources :users
end

  resources :users
end


回答2:

Rails is a bit confusing, but I had a similar problem. Here's some steps you can take to make sure you're not missing any small code issues. (this eventually led me to discover a syntax bug in the namespaced controller).

  1. run bundle exec rake routes to generate a list of what route links to what controller and action. If this is good, then move to step 2. If not, fix your routes file and try again. (many good tutorials on this, so I won't go into detail)
  2. Go into the rails console, and just load the controller class. If it doesn't work, you may have discovered a bug in syntax. Here's what happened on console when I tried to load the Api::V2::CampaignsController.

    irb> Api::V2::CampaignsController

    => CampaignsController

Note: Rails is directing all requests to the wrong controller (based on Rails' fancy logic to load controller classes). It should goto Api::V2::CampaignsController, but instead it is loading CampaignsController.

You can also verify it in the console with:

> app.get '/api/v2/campaigns.json'
> app.controller.class
=> CampaignsController
# This is not the expected controller. 

This ended up being a syntax problem in a class I was extending from the Api::V2::CampaignsController.

It was a bit mind-boggling, but hope this helps someone else.