Skip to content

Commit

Permalink
Merge 2f5c4c8 into 643c543
Browse files Browse the repository at this point in the history
  • Loading branch information
richardnuno committed Feb 28, 2014
2 parents 643c543 + 2f5c4c8 commit 7569156
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 14 deletions.
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,22 @@ The extraction strategies use a default string key of `api_version`, but that ca
config.versioncake.version_key = "special_version_parameter_name"
```

#### Response Header Key

When a value for the response_header_key property is defined, an HTTP header is added to the response. The field name will be the value specified for the property and the field value will be either "true" if the requested version is supported or "false" if it is not supported.
```ruby
config.versioncake.response_header_key = "X-API-Version-Supported"
```

You can then use the header value to notify the user if the requested version is unsupported. The following example uses jQuery's .ajaxComplete() to check for an unsupported version on all ajax requests.
```javascript
$(document).ajaxComplete(function(event, xhr, settings) {
if (xhr.getResponseHeader('X-API-Version-Supported') === "false") {
// Notify user of the unsupported version request
}
});
```

### 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.
Expand Down Expand Up @@ -277,6 +293,9 @@ def index
end
end
```

You can use `is_newer_version` and `is_older_version` to customize error handling on the controller. The `is_newer_version` is set to true when a consumer requests a version that is higher than the latest supported version. The `is_older_version` will be set to true when a consumer requests a deprecated version.

### 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``.
Expand Down
2 changes: 1 addition & 1 deletion lib/versioncake/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class Configuration
VERSION_KEY_DEFAULT = 'api_version'

attr_reader :extraction_strategies, :supported_version_numbers
attr_accessor :default_version, :version_key
attr_accessor :default_version, :version_key, :response_header_key

def initialize
@version_key = VERSION_KEY_DEFAULT
Expand Down
33 changes: 32 additions & 1 deletion lib/versioncake/controller_additions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,15 @@ module ControllerAdditions
# be the rendered version and may also be nil.
attr_accessor :requested_version

# A boolean check to determine if the requested version is deprecated.
attr_accessor :is_older_version

# A boolean check to determine if the latest version is requested.
attr_accessor :is_latest_version

# A boolean check to determine if the requested version is newer than any supported version.
attr_accessor :is_newer_version

# The requested version by a client or if it's nil the latest or default
# version configured.
attr_accessor :derived_version
Expand All @@ -33,8 +39,33 @@ def set_version(override_version=nil)
versioned_request = VersionCake::VersionedRequest.new(request, override_version)
@requested_version = versioned_request.extracted_version
@derived_version = versioned_request.version
@_lookup_context.versions = versioned_request.supported_versions
@is_older_version = versioned_request.is_older_version
@is_latest_version = versioned_request.is_latest_version
@is_newer_version = versioned_request.is_newer_version

set_response_header

raise ActionController::RoutingError.new("Version is deprecated") if versioned_request.is_older_version
raise ActionController::RoutingError.new("No route match for version") if versioned_request.is_newer_version

@_lookup_context.versions = versioned_request.supported_versions
end

private

# Adds a header field in the response with a name that corresponds
# to the value of the configuration's response_header_key variable.
# The value of the header field is "true" if the requested version
# is supported and "false" when it is not supported.
#
# The header is only added to the response when the configuration's
# response_header_key variable is defined.
#
# @return No explicit return, but sets a header in the response
def set_response_header
header_key = VersionCake::Railtie.config.versioncake.response_header_key
is_supported_version = !(@is_older_version || @is_newer_version)
headers[header_key] = is_supported_version.to_s if header_key
end
end
end
Expand Down
9 changes: 5 additions & 4 deletions lib/versioncake/versioned_request.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module VersionCake
class VersionedRequest
attr_reader :version, :extracted_version, :is_latest_version
attr_reader :version, :extracted_version, :is_latest_version,
:is_newer_version, :is_older_version

def initialize(request, version_override=nil)
@version = version_override || extract_version(request)
Expand All @@ -27,15 +28,15 @@ def apply_strategies(request)
end

def extract_version(request)
@is_newer_version = @is_older_version = false
@extracted_version = apply_strategies(request)
if @extracted_version.nil?
@version = config.default_version || config.latest_version
elsif config.supports_version? @extracted_version
@version = @extracted_version
elsif @extracted_version > config.latest_version
raise ActionController::RoutingError.new("No route match for version")
else
raise ActionController::RoutingError.new("Version is deprecated")
@is_newer_version = @extracted_version > config.latest_version
@is_older_version = !@is_newer_version
end
end
end
Expand Down
72 changes: 72 additions & 0 deletions test/functional/renders_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,78 @@ class RendersControllerTest < ActionController::TestCase
assert @controller.requested_version.blank?
end

test "is_newer_version is true if the requested version is larger than the supported versions" do
VersionCake::Configuration.any_instance.stubs(:default_version => 1)
get :index, "api_version" => "4" rescue ActionController::RoutingError
assert @controller.is_newer_version
end

test "is_newer_version is false if the requested version is a supported version" do
VersionCake::Configuration.any_instance.stubs(:default_version => 1)
get :index, "api_version" => "1"
assert !@controller.is_newer_version
end

test "is_newer_version is false if the requested version is a deprecated version" do
VersionCake::Configuration.any_instance.stubs(:default_version => 1)
get :index, "api_version" => "0" rescue ActionController::RoutingError
assert !@controller.is_newer_version
end

test "is_older_version is true if the requested version is a deprecated version" do
VersionCake::Configuration.any_instance.stubs(:default_version => 1)
get :index, "api_version" => "0" rescue ActionController::RoutingError
assert @controller.is_older_version
end

test "is_older_version is false if the requested version is a supported version" do
VersionCake::Configuration.any_instance.stubs(:default_version => 1)
get :index, "api_version" => "1"
assert !@controller.is_older_version
end

test "is_older_version is false if the requested version is larger than the supported versions" do
VersionCake::Configuration.any_instance.stubs(:default_version => 1)
get :index, "api_version" => "4" rescue ActionController::RoutingError
assert !@controller.is_older_version
end

test "a request for a deprecated version raises an exception" do
VersionCake::Configuration.any_instance.stubs(:default_version => 1)
assert_raise ActionController::RoutingError do
get :index, "api_version" => "0"
end
end

test "a request for a version that is higher than the latest version raises an exception" do
VersionCake::Configuration.any_instance.stubs(:default_version => 1)
assert_raise ActionController::RoutingError do
get :index, "api_version" => "4"
end
end

test "sets responses header value to true when the version is supported and response_header_key configuration is defined" do
response_header_key = 'x-version-supported'
VersionCake::Configuration.any_instance.stubs(:response_header_key => response_header_key)
get :index, "api_version" => "1"
assert_equal "true", @response.headers[response_header_key]
end

test "sets responses header value to false when the version is not supported and response_header_key configuration is defined" do
response_header_key = 'x-version-supported'
VersionCake::Configuration.any_instance.stubs(:response_header_key => response_header_key)
get :index, "api_version" => "0" rescue ActionController::RoutingError
assert_equal "false", @response.headers[response_header_key]
end

test "doesn't set a response header value when the response_header_key configuration is not defined" do
VersionCake::Configuration.any_instance.stubs(:response_header_key => nil)
get :index, "api_version" => "1"
@response.headers.each do |header_key, header_value|
assert !["true", "false"].include?(header_value)
end
end

test "set_version can be called to override the requested version" do
get :index, "api_version" => "1", "override_version" => 2
assert_equal 2, @controller.derived_version
Expand Down
26 changes: 18 additions & 8 deletions test/unit/versioned_request_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,29 @@ class VersionedRequestTest < ActiveSupport::TestCase
assert_equal 3, versioned_request.version
end

test "a request for a version that is higher than the latest version raises an error" do
test "has a method that returns true when a requested version is newer than any supported version" do
VersionCake::VersionedRequest.any_instance.stubs(:apply_strategies => 99)
assert_raise ActionController::RoutingError do
VersionCake::VersionedRequest.new(stub())
end
versioned_request = VersionCake::VersionedRequest.new(stub())
assert versioned_request.is_newer_version
end

test "has a method that returns false when a requested version isn't newer than any supported version" do
VersionCake::VersionedRequest.any_instance.stubs(:apply_strategies => 2)
versioned_request = VersionCake::VersionedRequest.new(stub())
assert !versioned_request.is_newer_version
end

test "a request for a deprecated version raises an exception" do
test "has a method that returns true when a requested version is deprecated" do
VersionCake::VersionedRequest.any_instance.stubs(:apply_strategies => 2)
VersionCake::Configuration.any_instance.stubs(:supports_version? => false)
assert_raise ActionController::RoutingError do
VersionCake::VersionedRequest.new(stub())
end
versioned_request = VersionCake::VersionedRequest.new(stub())
assert versioned_request.is_older_version
end

test "has a method that returns false when a requested version isn't deprecated" do
VersionCake::VersionedRequest.any_instance.stubs(:apply_strategies => 2)
versioned_request = VersionCake::VersionedRequest.new(stub())
assert !versioned_request.is_older_version
end

test "has a method to determine if requesting the latest version" do
Expand Down

0 comments on commit 7569156

Please sign in to comment.