README.md in versioncake-2.5.0 vs README.md in versioncake-3.0.0

- old
+ new

@@ -27,23 +27,44 @@ ## Install ``` gem install versioncake +rails g versioncake:install ``` ### Requirements -| Version | Rails 3.2 Support? | Rails 4 Support? | Rails 4.1 Support? | [Rails API](https://github.com/rails-api/rails-api) 0.2 Support? | -| ------- |:---------:| -------:| -------:| -------:| -| [1.0](CHANGELOG.md#100-march-14-2013) | Yes | No | No | No | -| [1.1](CHANGELOG.md#110-may-18-2013) | Yes | No | No | No | -| [1.2](CHANGELOG.md#120-may-26-2013) | Yes | Yes | No | No | -| [1.3](CHANGELOG.md#130-sept-26-2013) | Yes | Yes | No | No | -| [>2.0](CHANGELOG.md#200-feb-6-2014) | Yes | Yes | Yes | No | -| [>2.4](CHANGELOG.md#200-feb-6-2014) | Yes | Yes | Yes | Yes | +| Version | Rails 3.2 Support? | Rails 4 Support? | Rails >4.1 Support? | Rails >5 Support? | [Rails API](https://github.com/rails-api/rails-api) 0.2 Support? | +| -------:|:---------:| -------:| -------:| -------:| -------:| +| [1.0](CHANGELOG.md#100-march-14-2013) | Yes | No | No | No | No | +| [1.1](CHANGELOG.md#110-may-18-2013) | Yes | No | No | No | No | +| [1.2](CHANGELOG.md#120-may-26-2013) | Yes | Yes | No | No | No | +| [1.3](CHANGELOG.md#130-sept-26-2013) | Yes | Yes | No | No | No | +| [>2.0](CHANGELOG.md#200-feb-6-2014) | Yes | Yes | Yes | No | No | +| [>2.4](CHANGELOG.md#200-feb-6-2014) | Yes | Yes | Yes | No | Yes | +| [>3.0](CHANGELOG.md) | Yes | Yes | Yes | Yes | Yes | +## Upgrade v2.0 -> v3.0 + +### Accept header name changes + +The default accept header was changed from 'X-API-Version' to 'API-Version'. If you require the 'X-' or some other variant, you can specify a custom strategy as outlined in Extraction Strategy section below. + +### Configuration changes + +Configuration is now done with an initializer-you can generate a default one with `rails g versioncake:install` and then modify the generated file to match your configuration. + +### Configuration changes + +The configuration options for Version Cake have changed: + +| Old Name | New Name | +| -------------------------------------------- | ---------------------- | +| config.versioncake.supported_version_numbers | config.resources | +| config.versioncake.default_version | config.missing_version | + ## Upgrade v1.* -> v2.0 ### Filename changes The major breaking change to require a bump to v2.0 was the order of the extensions. To avoid priority issues with the format (#14), the version number and the format have been swapped. @@ -68,12 +89,17 @@ In this simple example we will outline the code that is introduced to support a change in a version. ### config/application.rb ```ruby -config.versioncake.supported_version_numbers = (1...4) -config.versioncake.extraction_strategy = :query_parameter # for simplicity +VersionCake.setup do |config| + config.resources do |r| + r.resource %r{.*}, [], [], (1..4) + end + config.extraction_strategy = :query_parameter # for simplicity + config.missing_version = 4 +end ``` Often times with APIs, depending upon the version, different logic needs to be applied. With the following controller code, the initial value of @posts includes all Post entries. But if the requested API version is three or greater, we're going to eagerly load the associated comments as well. @@ -85,11 +111,11 @@ def index # shared code for all versions @posts = Post.scoped # version 3 or greated supports embedding post comments - if derived_version >= 3 + if request_version >= 3 @posts = @posts.includes(:comments) end end end ``` @@ -158,11 +184,11 @@ } ] ``` -When no version is specified, the latest version of the view is rendered. In this case, views/posts/index.json.v4.jbuilder. +When no version is specified, the configured `missing_version` will be used to render a view. In this case, views/posts/index.json.v4.jbuilder. #### http://localhost:3000/posts.json ```javascript [ { @@ -193,33 +219,41 @@ ``` ## How to use ### Configuration -The configuration should be placed in your Rails projects `config/application.rb`. It is also suggested to enable different settings per environment, for example development and test can have extraction strategies that make it easier to develop or write test code. +The configuration lives in `config/initializers/versioncake.rb`. -#### Supported Versions -You need to define the supported versions in your Rails application.rb file as `view_versions`. Use this config to set the range of supported API versions that can be served: +#### Versioned Resources +Each individual resource uri can be identified by a regular expression. For each one it can be customized to have obsolete, deprecated, supported versions. ```ruby -config.versioncake.supported_version_numbers = [1,2,3,4,5] # or (1..5) + config.resources do |r| + # r.resource uri_regex, obsolete, deprecated, supported + + # version 2 and 3 are still supported on users resource + r.resource %r{/users}, [1], [2,3], [4] + + # all other resources only allow v4 + r.resource %r{.*}, [1,2,3], [], [4] + end ``` #### Extraction Strategy -You can also define the way to extract the version. The `view_version_extraction_strategy` allows you to set one of the default strategies or provide a proc to set your own. You can also pass it a prioritized array of the strategies. +You can also define the way to extract the version. The `extraction_strategy` allows you to set one of the default strategies or provide a proc to set your own. You can also pass it a prioritized array of the strategies. ```ruby -config.versioncake.extraction_strategy = :query_parameter # [:http_header, :http_accept_parameter] +config.extraction_strategy = :query_parameter # [:http_header, :http_accept_parameter] ``` These are the available strategies: Strategy | Description | Example --- | --- | --- :query_parameter | version in the url query parameter, for testing or to override for special case | `http://localhost:3000/posts.json?api_version=1` (This is the default.) :path_parameter | version in the url path parameter | `api/v:api_version/` -request_parameter | version that is sent in the body of the request | Good for testing. -:http_header | Api version HTTP header | `X-API-Version: 1` +:request_parameter | version that is sent in the body of the request | Good for testing. +:http_header | Api version HTTP header | `API-Version: 1` :http_accept_parameter | HTTP Accept header | `Accept: application/xml; version=1` [why do this?](http://blog.steveklabnik.com/posts/2011-07-03-nobody-understands-rest-or-http#i_want_my_api_to_be_versioned) custom | takes the request object and must return an integer | lambda {&#124;request&#124; request.headers["HTTP_X_MY_VERSION"].to_i } or class ExtractorStrategy; def execute(request);end;end If you use the path_parameter strategy with resources routes, you will want to setup your routes.rb config file to capture the api version. You can do that in a few ways. If you have just a few api routes you might specify the path directly like this: ``` @@ -234,20 +268,26 @@ #### Default Version When no version is supplied by a client, the version rendered will be the latest version by default. If you want to override this to another version, set the following property: ```ruby -config.versioncake.default_version = 4 +config.missing_version = 4 ``` #### Version String The extraction strategies use a default string key of `api_version`, but that can be changed: ```ruby -config.versioncake.version_key = "special_version_parameter_name" +config.version_key = "special_version_parameter_name" ``` +#### Version String +If you do not wish to use the magic mapping of the version number to templates it can be disabled: +```ruby +config.rails_view_versioning = false +``` + ### Version your views When a client makes a request to your controller the latest version of the view will be rendered. The latest version is determined by naming the template or partial with a version number that you configured to support. ``` @@ -271,34 +311,44 @@ def index # shared code for all versions @posts = Post.scoped # version 3 or greated supports embedding post comments - if derived_version >= 3 + if request_version >= 3 @posts = @posts.includes(:comments) end end ``` ### Client requests When a client makes a request it will automatically receive the latest supported version of the view. The client can also request for a specific version by one of the strategies configured by ``view_version_extraction_strategy``. -### Unsupported Version Requests +### Raised exceptions -If a client requests a version that is no longer supported (is not included in the `config.versioncake.supported_version_numbers`), a `VersionCake::UnsupportedVersionError` will be raised. This can be handled using Rails `rescue_from` to return app specific messages to the client. +These are the types of exceptions VersionCake will raise: +|Exception type|Description| +|--------------|-----------| +|VersionCake::UnsupportedVersionError| The version is invalid, too high or too low for the resource.| +|VersionCake::ObsoleteVersionError|The version is obsolete for the resource.| +|VersionCake::MissingVersionError|If no `config.missing_version` is specified, this will be raised when no version is in the request.| + +### Handling Exceptions + +Handling exceptions can simply be done by using Rails `rescue_from` to return app specific messages to the client. + ```ruby class ApplicationController < ActionController::Base ... rescue_from VersionCake::UnsupportedVersionError, :with => :render_unsupported_version private def render_unsupported_version - headers['X-API-Version-Supported'] = 'false' + headers['API-Version-Supported'] = 'false' respond_to do |format| format.json { render json: {message: "You requested an unsupported version (#{requested_version})"}, status: :unprocessable_entity } end end @@ -315,19 +365,19 @@ ### Test configuration Allowing more extraction strategies during testing can be helpful when needing to override the version. ```ruby # config/environments/test.rb -config.versioncake.extraction_strategy = [:query_parameter, :request_parameter, :http_header, :http_accept_parameter] +config.extraction_strategy = [:query_parameter, :request_parameter, :http_header, :http_accept_parameter] ``` ### Testing a specific version One way to test a specific version for would be to stub the requested version in the before block: ```ruby before do - @controller.stubs(:requested_version).returns(3) + @controller.stubs(:request_version).returns(3) end ``` You can also test a specific version through a specific strategy such query_parameter or request_parameter strategies (configured in test environment) like so: ```ruby @@ -341,10 +391,10 @@ ### Testing all supported versions You can iterate over all of the supported version numbers by accessing the ```AppName::Application.config.versioncake.supported_version_numbers```. ```ruby -AppName::Application.config.versioncake.supported_version_numbers.each do |supported_version| +VersionCake.config.resources.first.supported_versions.each do |supported_version| before do @controller.stubs(:requested_version).returns(supported_version) end test "all versions render the correct template" do