我希望有人解释为什么在Rails(4.1.8)中使用Grape(0.10.1)发生这种情况
所以这是我的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
并在我的application.rb
中添加了:
config.paths.add "app/api", glob: "**/*.rb"
config.autoload_paths += Dir["#{Rails.root}/app/api/*"]
在这种情况下,我收到错误:NameError: uninitialized constant API
但如果我的代码如下:
app/api/root.rb
与上述相同
然后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
和config/application.rb
与上述相同
然后一切正常。
我的问题是为什么我不需要在v1/root.rb
内和v1/users
内指定模块,以及为什么我不需要在API::Root => '/'
中使用config/routes.rb
{1}}?
答案 0 :(得分:8)
这是因为app/api
是API类的顶级文件夹,而不是app
。
将API文件放入
app/api
。 Rails需要一个与Ruby模块名称匹配的子目录和一个与该类名称匹配的文件名。在我们的示例中,Twitter::API
的文件名位置和目录应为app/api/twitter/api.rb
。
因此,API::Root
类的正确位置实际上是app/api/api/root.rb
,而不是/app/api/root.rb
- 尽管 是顶级类的正确位置-level命名空间,这就是你给出的第二个例子(从API
模块中删除了类)的原因。
我建议您将API类保存在自己的模块中,并将它们移动到app/api
下面的匹配子文件夹。
答案 1 :(得分:1)
对于高于6.0.0.beta2的Rails版本,Zeitwerk
自动装载器是CRuby的默认值。默认情况下,Zeitwerk
将api
改为Api
而不是API
。为了使我们的示例生效,您需要取消注释config/initializers/inflections.rb
底部的行,并添加API
作为首字母缩写:
ActiveSupport::Inflector.inflections(:en) do |inflect|
inflect.acronym 'API'
end
答案 2 :(得分:0)
我尝试将我的文件放入app/api/api
,但它并不适合我。
我只需将api
文件夹放入controller
文件夹即可找到解决方案。我不是100%确定问题是什么,但我的猜测是它与自动加载的路径有关。