README.md in versioncake-1.3.0 vs README.md in versioncake-2.0.0
- old
+ new
@@ -12,14 +12,14 @@
- Easily version any view with their API version:
```ruby
app/views/posts/
- - index.v1.xml.builder
- - index.v3.xml.builder
- - index.v1.json.jbuilder
- - index.v4.json.jbuilder
+ - index.xml.v1.builder
+ - index.xml.v3.builder
+ - index.json.v1.jbuilder
+ - index.json.v4.jbuilder
```
- Gracefully degrade requests to the latest supported version
- Clients can request API versions through different strategies
- Dry your controller logic with exposed helpers
@@ -31,20 +31,48 @@
gem install versioncake
```
### Requirements
-Rails >= v3.2 is supported in versioncake =< v1.1. Rails 4 support is included versioncake >= v1.2.
+| Version | Rails 3.2 Support? | Rails 4 Support? | Rails 4.1 Support? |
+| ------- |:---------:| -------:| -------:|
+| 1.0 | Yes | No | No |
+| 1.1 | Yes | No | No |
+| 1.2 | Yes | Yes | No |
+| 1.3 | Yes | Yes | No |
+| 2.0 | Yes | Yes | Yes |
+## Upgrade v1.0 -> 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.
+
+`index.v1.json.jbuilder` -> `index.json.v1.jbuilder`
+
+To make it easier to upgrade, run the following command to automatically rename these files:
+
+`verisoncake migrate` or `verisoncake migrate path/to/views`
+
+### Configuration changes
+
+The configuration options for Version Cake have been namespaced and slightly renamed. The following is a mapping of the old names to the new names:
+
+| Old Name | New Name |
+| --------------------------------------- | -------------------------------------------- |
+| config.view_versions | config.versioncake.supported_version_numbers |
+| config.view_version_extraction_strategy | config.versioncake.extraction_strategy |
+| config.view_version_string | config.versioncake.version_key |
+| config.default_version | config.versioncake.default_version |
+
## Example
In this simple example we will outline the code that is introduced to support a change in a version.
### config/application.rb
```ruby
-config.view_versions = (1...4)
-config.view_version_extraction_strategy = :query_parameter # for simplicity
+config.versioncake.supported_version_numbers = (1...4)
+config.versioncake.extraction_strategy = :query_parameter # for simplicity
```
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.
@@ -63,35 +91,35 @@
end
end
end
```
-See the view samples below. The basic top level posts are referenced in views/posts/index.v1.json.jbuilder.
-But for views/posts/index.v4.json.jbuilder, we utilize the additional related comments.
+See the view samples below. The basic top level posts are referenced in views/posts/index.json.v1.jbuilder.
+But for views/posts/index.json.v4.jbuilder, we utilize the additional related comments.
### Views
Notice the version numbers are denoted by the "v{version number}" extension within the file name.
-#### views/posts/index.v1.json.jbuilder
+#### views/posts/index.json.v1.jbuilder
```ruby
json.array!(@posts) do |json, post|
json.(post, :id, :title)
end
```
-#### views/posts/index.v4.json.jbuilder
+#### views/posts/index.json.v4.jbuilder
```ruby
json.array!(@posts) do |json, post|
json.(post, :id, :title)
json.comments post.comments, :id, :text
end
```
### Sample Output
-When a version is specified for which a view doesn't exist, the request degrades and renders the next lowest version number to ensure the API's backwards compatibility. In the following case, since views/posts/index.v3.json.jbuilder doesn't exist, views/posts/index.v1.json.jbuilder is rendered instead.
+When a version is specified for which a view doesn't exist, the request degrades and renders the next lowest version number to ensure the API's backwards compatibility. In the following case, since views/posts/index.json.v3.jbuilder doesn't exist, views/posts/index.json.v1.jbuilder is rendered instead.
#### http://localhost:3000/posts.json?api_version=3
```javascript
[
{
@@ -108,11 +136,11 @@
}
]
```
-For a given request, if we specify the version number, and that version of the view exists, that version specific view version will be rendered. In the below case, views/posts/index.v1.json.jbuilder is rendered.
+For a given request, if we specify the version number, and that version of the view exists, that version specific view version will be rendered. In the below case, views/posts/index.json.v1.jbuilder is rendered.
#### http://localhost:3000/posts.json?api_version=2 or http://localhost:3000/posts.json?api_version=1
```javascript
[
{
@@ -129,11 +157,11 @@
}
]
```
-When no version is specified, the latest version of the view is rendered. In this case, views/posts/index.v4.json.jbuilder.
+When no version is specified, the latest version of the view is rendered. In this case, views/posts/index.json.v4.jbuilder.
#### http://localhost:3000/posts.json
```javascript
[
{
@@ -170,39 +198,43 @@
#### 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:
```ruby
-config.view_versions = [1,2,3,4,5] # or (1..5)
+config.versioncake.supported_version_numbers = [1,2,3,4,5] # or (1..5)
```
#### 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.
```ruby
-config.view_version_extraction_strategy = :query_parameter # [:http_header, :http_accept_parameter]
+config.versioncake.extraction_strategy = :query_parameter # [:http_header, :http_accept_parameter]
```
These are the available strategies:
- - **query_parameter**: version in the url query parameter, for testing or to override for special case i.e. ```http://localhost:3000/posts.json?api_version=1``` (This is the default.)
- - **request_parameter**: version that is sent in the body of the request. Good for testing.
- - **http_header**: Api version HTTP header ie. ```X-API-Version: 1```
- - **http_accept_parameter**: HTTP Accept header ie. ```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**: `lambda {|request| request.headers["HTTP_X_MY_VERSION"].to_i }` takes the request object and must return an integer
+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`
+: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 {|request| request.headers["HTTP_X_MY_VERSION"].to_i }
+
#### 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.default_version = 4
+config.versioncake.default_version = 4
```
#### Version String
The extraction strategies use a default string key of `api_version`, but that can be changed:
```ruby
-config.view_version_string = "special_version_parameter_name"
+config.versioncake.version_key = "special_version_parameter_name"
```
### 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.
@@ -211,12 +243,12 @@
- app/views/posts
- index.html.erb
- edit.html.erb
- show.html.erb
- show.json.jbuilder
- - show.v1.json.jbuilder
- - show.v2.json.jbuilder
+ - show.json.v1.jbuilder
+ - show.json.v2.jbuilder
- new.html.erb
- _form.html.erb
```
If you start supporting a newer version, v3 for instance, you do not have to copy posts/show.v2 to posts/show.v3. By default, the request for v3 or higher will gracefully degrade to the view that is the newest, supported version, in this case posts/show.v2.
@@ -246,11 +278,11 @@
### Test configuration
Allowing more extraction strategies during testing can be helpful when needing to override the version.
```ruby
# config/environments/test.rb
-config.view_version_extraction_strategy = [:query_parameter, :request_parameter, :http_header, :http_accept_parameter]
+config.versioncake.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:
@@ -263,27 +295,27 @@
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
# test/functional/renders_controller_test.rb#L47
test "render version 1 of the partial based on the parameter _api_version" do
get :index, "api_version" => "1"
- assert_equal @response.body, "index.v1.html.erb"
+ assert_equal @response.body, "index.html.v1.erb"
end
```
### Testing all supported versions
-You can iterate over all of the supported version numbers by accessing the ```AppName::Application.config.view_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.view_versions.each do |supported_version|
+AppName::Application.config.versioncake.supported_version_numbers.each do |supported_version|
before do
@controller.stubs(:requested_version).returns(supported_version)
end
test "all versions render the correct template" do
get :index
- assert_equal @response.body, "index.v1.html.erb"
+ assert_equal @response.body, "index.html.v1.erb"
end
end
```
# Thanks!
@@ -294,9 +326,12 @@
* [Alicia](https://github.com/alicial)
* [Rohit](https://github.com/rg)
* Sevag
* [Billy](https://github.com/bcatherall)
* [Jérémie Meyer de Ville](https://github.com/jeremiemv)
+* [Michael Elfassy](https://github.com/elfassy)
+* [Kelley Reynolds](https://github.com/kreynolds)
+* [Washington L Braga Jr](https://github.com/huoxito)
# Related Material
## Usages