Why does trying to use Grape with Rails fail with “uninitialized constant API”?

≯℡__Kan透↙ 提交于 2019-12-01 11:47:55

问题


I would like someone to explain why this is happening in Rails (4.1.8) with Grape (0.10.1)

so this is my API:

app/api/root.rb:

module API
  class Root < Grape::API
    prefix 'api'
    mount API::V1::Root
  end
end

app/api/v1/root.rb:

module API::V1
  class Root < Grape::API
    version 'v1'
    mount API::V1::Users
  end
end

app/api/v1/users.rb:

module API::V1
  class Users < Grape::API
    format 'json'

    resource :users do
      desc "Return list of users"
      get '/' do
        User.all
      end
    end
  end
end

config/routes.rb:

Rails.application.routes.draw do
  mount API::Root => '/'
end

and in my application.rb I added:

config.paths.add "app/api", glob: "**/*.rb"
config.autoload_paths += Dir["#{Rails.root}/app/api/*"]

and in that case I get the error: NameError: uninitialized constant API


but if my code looks like:

app/api/root.rb same as above

then app/api/v1/root.rb:

class Root < Grape::API
  version 'v1'
  mount Users
end

app/api/v1/users.rb:

class Users < Grape::API
  format 'json'

  resource :users do
    desc "Return list of users"
    get '/' do
      User.all
    end
  end
end

config/routes.rb:

Rails.application.routes.draw do
  mount Root => '/'
end

and config/application.rb same as above

Then everything works fine.

My question is why don't I need to specify modules inside v1/root.rb and also inside v1/users and also why I don't need to use API::Root => '/' in config/routes.rb?


回答1:


It's because app/api is the top-level folder for your API classes, not app.

From Grape's documentation:

Place API files into app/api. Rails expects a subdirectory that matches the name of the Ruby module and a file name that matches the name of the class. In our example, the file name location and directory for Twitter::API should be app/api/twitter/api.rb.

Therefore the correct location for an API::Root class would actually be app/api/api/root.rb, not /app/api/root.rb—though that is the correct location for a class in the top-level namespace, which is why the second example you give (with classes removed from the API module) works.

I recommend you keep your API classes together in their own module, though, and move them to a matching subfolder beneath app/api.




回答2:


I tried to put my files into app/api/api, but it wasn't working for me.

I found a solution by simply putting the api folder into the controller folder. I'm not 100% sure what the problem was, but my guess is that it has something to do with the auto-loaded paths.




回答3:


From Grape's documentation:

For Rails versions greater than 6.0.0.beta2, Zeitwerk autoloader is the default for CRuby. By default Zeitwerk inflects api as Api instead of API. To make our example work, you need to uncomment the lines at the bottom of config/initializers/inflections.rb, and add API as an acronym:

ActiveSupport::Inflector.inflections(:en) do |inflect|
  inflect.acronym 'API'
end


来源:https://stackoverflow.com/questions/28109784/why-does-trying-to-use-grape-with-rails-fail-with-uninitialized-constant-api

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!