为什么尝试使用Grape with Rails失败了“未初始化的常量API”?

时间:2015-01-23 12:20:06

标签: ruby-on-rails ruby api ruby-on-rails-4 grape

我希望有人解释为什么在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}}?

3 个答案:

答案 0 :(得分:8)

这是因为app/api是API类的顶级文件夹,而不是app

来自Grape's documentation

  

将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)

来自Grape's documentation

对于高于6.0.0.beta2的Rails版本,Zeitwerk自动装载器是CRuby的默认值。默认情况下,Zeitwerkapi改为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%确定问题是什么,但我的猜测是它与自动加载的路径有关。