Skip to content

Commit

Permalink
Fixes #14
Browse files Browse the repository at this point in the history
* Moving position of version extension to end of the filename to avoid
priority collisions when format is not present
* Fixing/renaming tests for new names
* updating changelog
  • Loading branch information
bwillis committed Sep 28, 2013
1 parent e682953 commit 80efcc5
Show file tree
Hide file tree
Showing 11 changed files with 45 additions and 35 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

[Full Changelog](https://github.com/bwillis/versioncake/compare/v1.3...master)

Bug Fixes:

* Adjusting view details priorities so that RABL templates that do not have a format are not prioritized over templates that do have a format (issues #14). This is going to go into v2 as it is a breaking change.

## 1.3.0 (Sept 26, 2013)

[Full Changelog](https://github.com/bwillis/versioncake/compare/v1.2...v1.3)
Expand Down
36 changes: 21 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ Version Cake is an unobtrusive way to version APIs in your Rails app.

```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
Expand All @@ -35,6 +35,12 @@ gem install versioncake

Rails >= v3.2 is supported in versioncake =< v1.1. Rails 4 support is included versioncake >= v1.2.

## Upgrade v1.0 -> v2.0

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`

## Example

In this simple example we will outline the code that is introduced to support a change in a version.
Expand Down Expand Up @@ -65,21 +71,21 @@ class PostsController < ApplicationController
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)
Expand All @@ -89,7 +95,7 @@ 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
Expand All @@ -110,7 +116,7 @@ When a version is specified for which a view doesn't exist, the request degrades
```


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
Expand All @@ -131,7 +137,7 @@ For a given request, if we specify the version number, and that version of the v
```


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
Expand Down Expand Up @@ -213,8 +219,8 @@ When a client makes a request to your controller the latest version of the view
- 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
```
Expand Down Expand Up @@ -265,7 +271,7 @@ You can also test a specific version through a specific strategy such query_para
# 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
```

Expand All @@ -281,7 +287,7 @@ AppName::Application.config.view_versions.each do |supported_version|

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
```
Expand Down
4 changes: 2 additions & 2 deletions lib/versioncake/view_additions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
ActionView::PathResolver.class_eval do

# not sure why we are doing this yet, but looks like a good idea
ActionView::PathResolver::EXTENSIONS.replace [:locale, :versions, :formats, :handlers]
ActionView::PathResolver::EXTENSIONS.replace [:locale, :formats, :versions, :handlers]

# The query builder has the @details from the lookup_context and will
# match the detail name to the string in the pattern, so we must append
# it to the default pattern
ActionView::PathResolver::DEFAULT_PATTERN.replace ":prefix/:action{.:locale,}{.:versions,}{.:formats,}{.:handlers,}"
ActionView::PathResolver::DEFAULT_PATTERN.replace ":prefix/:action{.:locale,}{.:formats,}{.:versions,}{.:handlers,}"

end

Expand Down
File renamed without changes.
File renamed without changes.
1 change: 0 additions & 1 deletion test/app/views/renders/index.v1.html.erb

This file was deleted.

1 change: 0 additions & 1 deletion test/app/views/renders/index.v2.html.erb

This file was deleted.

1 change: 1 addition & 0 deletions test/fixtures/templates/versioned.html.v1.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
template v1
1 change: 1 addition & 0 deletions test/fixtures/templates/versioned.html.v2.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
template v2
32 changes: 16 additions & 16 deletions test/functional/renders_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class RendersControllerTest < ActionController::TestCase

test "render latest version of partial" do
get :index
assert_equal @response.body, "index.v2.html.erb"
assert_equal @response.body, "template v2"
end

test "exposes the requested version" do
Expand Down Expand Up @@ -65,17 +65,17 @@ class ParameterStrategyTest < ActionController::TestCase

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, "template v1"
end

test "render version 2 of the partial based on the parameter _api_version" do
get :index, "api_version" => "2"
assert_equal @response.body, "index.v2.html.erb"
assert_equal @response.body, "template v2"
end

test "render the latest available version (v2) of the partial based on the parameter _api_version" do
get :index, "api_version" => "3"
assert_equal @response.body, "index.v2.html.erb"
assert_equal @response.body, "template v2"
end
end

Expand All @@ -89,19 +89,19 @@ class CustomHeaderStrategyTest < ActionController::TestCase
test "renders version 1 of the partial based on the header API-Version" do
@controller.request.stubs(:headers).returns({"HTTP_X_API_VERSION" => "1"})
get :index
assert_equal @response.body, "index.v1.html.erb"
assert_equal @response.body, "template v1"
end

test "renders version 2 of the partial based on the header API-Version" do
@controller.request.stubs(:headers).returns({"HTTP_X_API_VERSION" => "2"})
get :index
assert_equal @response.body, "index.v2.html.erb"
assert_equal @response.body, "template v2"
end

test "renders the latest available version (v2) of the partial based on the header API-Version" do
@controller.request.stubs(:headers).returns({"HTTP_X_API_VERSION" => "3"})
get :index
assert_equal @response.body, "index.v2.html.erb"
assert_equal @response.body, "template v2"
end
end

Expand All @@ -128,32 +128,32 @@ class AcceptHeaderStrategyTest < ActionController::TestCase
test "render version 1 of the partial based on the header Accept" do
@controller.request.stubs(:headers).returns({"HTTP_ACCEPT" => "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8;api_version=1"})
get :index
assert_equal @response.body, "index.v1.html.erb"
assert_equal @response.body, "template v1"
end

test "render version 2 of the partial based on the header Accept" do
@controller.request.stubs(:headers).returns({"HTTP_ACCEPT" => "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8;api_version=2"})
get :index
assert_equal @response.body, "index.v2.html.erb"
assert_equal @response.body, "template v2"
end

test "render the latest available version (v2) of the partial based on the header Accept" do
@controller.request.stubs(:headers).returns({"HTTP_ACCEPT" => "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8;api_version=3"})
get :index
assert_equal @response.body, "index.v2.html.erb"
assert_equal @response.body, "template v2"
end

test "render the latest version of the partial" do
@controller.request.stubs(:headers).returns({"HTTP_ACCEPT" => "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8;api_version=abc"})
get :index
assert_equal @response.body, "index.v2.html.erb"
assert_equal @response.body, "template v2"
end

test "render the default version version of the partial" do
VersionCake::Configuration.default_version = 1
@controller.request.stubs(:headers).returns({"HTTP_ACCEPT" => "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8;api_version=abc"})
get :index
assert_equal @response.body, "index.v1.html.erb"
assert_equal @response.body, "template v1"
VersionCake::Configuration.default_version = nil
end

Expand All @@ -168,7 +168,7 @@ class CustomStrategyTest < ActionController::TestCase

test "renders version 2 of the partial based on the header Accept" do
get :index
assert_equal @response.body, "index.v2.html.erb"
assert_equal @response.body, "template v2"
end
end

Expand All @@ -182,18 +182,18 @@ class MultipleStrategyTest < ActionController::TestCase
test "renders version 1 of the partial based on the header Accept" do
@controller.request.stubs(:headers).returns({"HTTP_ACCEPT" => "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8;api_version=1"})
get :index
assert_equal @response.body, "index.v1.html.erb"
assert_equal @response.body, "template v1"
end

test "renders the query parameter when accept parameter isn't available" do
get :index, "api_version" => "1"
assert_equal @response.body, "index.v1.html.erb"
assert_equal @response.body, "template v1"
end

test "renders the higher priority accept parameter version" do
@controller.request.stubs(:headers).returns({"HTTP_ACCEPT" => "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8;api_version=2"})
get :index, "api_version" => "1"
assert_equal @response.body, "index.v2.html.erb"
assert_equal @response.body, "template v2"
end
end

Expand Down

0 comments on commit 80efcc5

Please sign in to comment.