我正在开发一个主要用作 API 的应用程序(除了一些次要视图,例如会话/注册,这将是“标准”)。我喜欢Railscast #350: Versioning an API中最终确定的方法,因此遵循了它。我的路线看起来像:
namespace :api, :defaults => {:format => 'json'} do
scope :module => :v1, :constraints => ApiConstraints.new(:version => 1, :default => false) do
resources :posts, :only => [:create, :show, :destroy, :index]
end
scope :module => :v2, :constraints => ApiConstraints.new(:version => 2, :default => true) do
resources :posts, :only => [:create, :show, :destroy, :index]
end
end
在每条路线中,我的约束是一个新的 ApiConstraints 对象,它位于我的./lib
文件夹中。该类如下所示:
class ApiConstraints
def initialize(options)
@version = options[:version]
@default = options[:default]
end
def matches?(req)
@default || req.headers['Accept'].include?("application/vnd.MYAPP.v#{@version}")
end
end
现在,当手动测试时,一切都按预期工作。在我的 API 中,每个版本我可能有 5 到 10 个控制器,并且不想测试 API 约束是否适用于每个单独的控制器,因为这没有任何意义。我正在寻找一个测试我的 API 约束的规范文件,但我不确定将该规范放在哪里。
我试过添加一个spec/routing/api_spec.rb
文件来测试东西,但它不能正常工作,因为它抱怨没有提供一些东西,就像这样:
it "should route an unversioned request to the latest version" do
expect(:get => "/api/posts", :format => "json").to route_to(:controller => "api/v1/posts")
end
即使控制器正确匹配,上述内容也会引发错误。它失败并出现以下错误:
The recognized options <{"format"=>"json", "action"=>"index", "controller"=>"api/v1/posts"}>
did not match <{"controller"=>"api/v1/posts"}>,
difference: <{"format"=>"json", "action"=>"index"}>.
请注意,控制器已正确确定,但由于我不想在此测试中测试格式和操作,因此会出错。我希望有 3 个“API 规范”:
- 它应该将未版本化的请求路由到最新版本
- 如果没有指定,它应该默认为 JSON 格式
- 它应该在请求时返回指定的 API 版本
有没有人有为这类路线编写规范的经验?我不想为 API 中的每个控制器添加规范,因为它们不负责此功能。