Я работаю над приложением, которое будет в основном использоваться как API (кроме нескольких второстепенных видов, таких как сеанс/регистрация, который будет "стандартным" ). Мне нравится подход, который был завершен в Railscast # 350: Versioning 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
В каждом маршруте мой Constraint - это новый объект 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, так как они не отвечают за эту функциональность.