Skip to content

Commit

Permalink
Merge branch 'feature-configuration_refactoring'
Browse files Browse the repository at this point in the history
  • Loading branch information
bwillis committed Feb 6, 2014
2 parents 00e2342 + c0d8705 commit 4a5d2cd
Show file tree
Hide file tree
Showing 17 changed files with 84 additions and 91 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Enhancements:
* New path strategy to support `/v3/posts` style versioning, thanks [Michael Elfassy](https://github.com/elfassy)
* Support Rails 4.1, thanks [Washington L Braga Jr](https://github.com/huoxito)
* Added v1->v2 template renaming migration script
* Improving configuration

## 1.3.0 (Sept 26, 2013)

Expand Down
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ gem install versioncake

## 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`
Expand All @@ -51,6 +52,17 @@ To make it easier to upgrade, run the following command to automatically rename

`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.
Expand Down
42 changes: 21 additions & 21 deletions lib/versioncake/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,47 @@
require 'active_support/core_ext/array/wrap.rb'

module VersionCake
module Configuration
class Configuration

SUPPORTED_VERSIONS_DEFAULT = (1..10)
VERSION_KEY_DEFAULT = 'api_version'

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

mattr_accessor :extraction_strategies
self.extraction_strategies = []

mattr_accessor :default_version
self.default_version = nil
def initialize
@version_key = VERSION_KEY_DEFAULT
self.supported_version_numbers = SUPPORTED_VERSIONS_DEFAULT
self.extraction_strategy = :query_parameter
end

def self.extraction_strategy=(val)
@@extraction_strategies.clear
def extraction_strategy=(val)
@extraction_strategies = []
Array.wrap(val).each do |configured_strategy|
@@extraction_strategies << VersionCake::ExtractionStrategy.lookup(configured_strategy)
@extraction_strategies << VersionCake::ExtractionStrategy.lookup(configured_strategy)
end
end

def self.supported_version_numbers=(val)
@@supported_version_numbers = val.respond_to?(:to_a) ? val.to_a : Array.wrap(val)
@@supported_version_numbers.sort!.reverse!
def supported_version_numbers=(val)
@supported_version_numbers = val.respond_to?(:to_a) ? val.to_a : Array.wrap(val)
@supported_version_numbers.sort!.reverse!
end

def self.supported_versions(requested_version_number=nil)
supported_version_numbers.collect do |supported_version_number|
def supported_versions(requested_version_number=nil)
@supported_version_numbers.collect do |supported_version_number|
if requested_version_number.nil? || supported_version_number <= requested_version_number
:"v#{supported_version_number}"
end
end
end

def self.supports_version?(version)
supported_version_numbers.include? version
def supports_version?(version)
@supported_version_numbers.include? version
end

def self.latest_version
supported_version_numbers.first
def latest_version
@supported_version_numbers.first
end

self.extraction_strategy = :query_parameter
self.supported_version_numbers = SUPPORTED_VERSIONS_DEFAULT
end
end
22 changes: 3 additions & 19 deletions lib/versioncake/railtie.rb
Original file line number Diff line number Diff line change
@@ -1,23 +1,7 @@
require 'rails'

class ActionViewVersions < Rails::Railtie
initializer "view_versions" do |app|
ActiveSupport.on_load(:action_view) do
if app.config.respond_to?(:view_versions)
VersionCake::Configuration.supported_version_numbers = app.config.view_versions
end

if app.config.respond_to?(:view_version_extraction_strategy)
VersionCake::Configuration.extraction_strategy = app.config.view_version_extraction_strategy
end

if app.config.respond_to?(:view_version_string)
VersionCake::ExtractionStrategy.version_string = app.config.view_version_string
end

if app.config.respond_to?(:default_version)
VersionCake::Configuration.default_version = app.config.default_version
end
end
module VersionCake
class Railtie < ::Rails::Railtie
config.versioncake = VersionCake::Configuration.new
end
end
12 changes: 4 additions & 8 deletions lib/versioncake/strategies/extraction_strategy.rb
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
if defined?(ActionPack::VERSION::MAJOR) && ActionPack::VERSION::MAJOR == 4 && ActionPack::VERSION::MINOR >= 1
require 'active_support/core_ext/module/attribute_accessors'
else
require 'active_support/core_ext/class/attribute_accessors.rb'
end
require 'active_support/core_ext/string/inflections.rb'

module VersionCake
class ExtractionStrategy

cattr_accessor :version_string
@@version_string = 'api_version'

def extract(request)
version = execute(request)
return version.to_i if version && /[0-9]+/.match(version)
end

def version_key
VersionCake::Railtie.config.versioncake.version_key
end

def execute(request)
raise Exception, "ExtractionStrategy requires execute to be implemented"
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ class HttpAcceptParameterStrategy < ExtractionStrategy

def execute(request)
if request.headers.key?("HTTP_ACCEPT") &&
match = request.headers["HTTP_ACCEPT"].match(/#{@@version_string}=([0-9]+)/)
match = request.headers["HTTP_ACCEPT"].match(/#{version_key}=([0-9]+)/)
match[1]
end
end
Expand Down
4 changes: 2 additions & 2 deletions lib/versioncake/strategies/http_header_strategy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ module VersionCake
class HttpHeaderStrategy < ExtractionStrategy

def execute(request)
if request.headers.key? "HTTP_X_#{@@version_string.upcase}"
request.headers["HTTP_X_#{@@version_string.upcase}"]
if request.headers.key? "HTTP_X_#{version_key.upcase}"
request.headers["HTTP_X_#{version_key.upcase}"]
end
end

Expand Down
4 changes: 2 additions & 2 deletions lib/versioncake/strategies/path_parameter_strategy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ module VersionCake
class PathParameterStrategy < ExtractionStrategy

def execute(request)
if request.path_parameters.key? @@version_string.to_sym
request.path_parameters[@@version_string.to_sym]
if request.path_parameters.key? version_key.to_sym
request.path_parameters[version_key.to_sym]
end
end

Expand Down
4 changes: 2 additions & 2 deletions lib/versioncake/strategies/query_parameter_strategy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ module VersionCake
class QueryParameterStrategy < ExtractionStrategy

def execute(request)
if request.query_parameters.key? @@version_string.to_sym
request.query_parameters[@@version_string.to_sym].to_s
if request.query_parameters.key? version_key.to_sym
request.query_parameters[version_key.to_sym].to_s
end
end

Expand Down
4 changes: 2 additions & 2 deletions lib/versioncake/strategies/request_parameter_strategy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ module VersionCake
class RequestParameterStrategy < ExtractionStrategy

def execute(request)
if request.request_parameters.has_key? @@version_string.to_sym
request.request_parameters[@@version_string.to_sym]
if request.request_parameters.has_key? version_key.to_sym
request.request_parameters[version_key.to_sym]
end
end

Expand Down
16 changes: 10 additions & 6 deletions lib/versioncake/versioned_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,22 @@ class VersionedRequest

def initialize(request, version_override=nil)
@version = version_override || extract_version(request)
@is_latest_version = @version == VersionCake::Configuration.latest_version
@is_latest_version = @version == config.latest_version
end

def supported_versions
VersionCake::Configuration.supported_versions(@version)
config.supported_versions(@version)
end

private

def config
VersionCake::Railtie.config.versioncake
end

def apply_strategies(request)
version = nil
VersionCake::Configuration.extraction_strategies.each do |strategy|
config.extraction_strategies.each do |strategy|
version = strategy.extract(request)
break unless version.nil?
end
Expand All @@ -25,10 +29,10 @@ def apply_strategies(request)
def extract_version(request)
@extracted_version = apply_strategies(request)
if @extracted_version.nil?
@version = VersionCake::Configuration.default_version || VersionCake::Configuration.latest_version
elsif VersionCake::Configuration.supports_version? @extracted_version
@version = config.default_version || config.latest_version
elsif config.supports_version? @extracted_version
@version = @extracted_version
elsif @extracted_version > VersionCake::Configuration.latest_version
elsif @extracted_version > config.latest_version
raise ActionController::RoutingError.new("No route match for version")
else
raise ActionController::RoutingError.new("Version is deprecated")
Expand Down
2 changes: 1 addition & 1 deletion lib/versioncake/view_additions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# register an addition detail for the lookup context to understand,
# this will allow us to have the versions available upon lookup in
# the resolver.
ActionView::LookupContext.register_detail(:versions){ VersionCake::Configuration.supported_versions }
ActionView::LookupContext.register_detail(:versions){ VersionCake::Railtie.config.versioncake.supported_versions }

ActionView::PathResolver.class_eval do
# not sure why we are doing this yet, but looks like a good idea
Expand Down
5 changes: 3 additions & 2 deletions test/config/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ class Application < Rails::Application
config.eager_load = false

config.active_support.deprecation = :stderr
config.view_versions = (1..3)
config.view_version_extraction_strategy = [:http_header, :http_accept_parameter, :query_parameter, :request_parameter]

config.versioncake.supported_version_numbers = (1..3)
config.versioncake.extraction_strategy = [:http_header, :http_accept_parameter, :query_parameter, :request_parameter]
end
end
2 changes: 1 addition & 1 deletion test/functional/custom_strategy_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class CustomStrategyTest < ActionController::TestCase
tests RendersController

setup do
VersionCake::Configuration.stubs(:extraction_strategy => lambda { |request| 2 })
VersionCake::Configuration.any_instance.stubs(:extraction_strategy => lambda { |request| 2 })
end

test "renders version 2 of the partial based on the header Accept" do
Expand Down
7 changes: 3 additions & 4 deletions test/functional/renders_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class RendersControllerTest < ActionController::TestCase
end

test "exposes the default version when the version is not set default is set" do
VersionCake::Configuration.stubs(:default_version => 1)
VersionCake::Configuration.any_instance.stubs(:default_version => 1)
get :index
assert_equal 1, @controller.derived_version
end
Expand All @@ -52,14 +52,13 @@ class RendersControllerTest < ActionController::TestCase
end

test "responds with 404 when the version is lower than the latest version, but not an available version" do
VersionCake::Configuration.stubs(:supported_version_numbers => [2,3])
assert_raise ActionController::RoutingError do
get :index, "api_version" => "1"
get :index, "api_version" => "0"
end
end

test "render the default version version of the partial" do
VersionCake::Configuration.stubs(:default_version => 1)
VersionCake::Configuration.any_instance.stubs(:default_version => 1)
get :index, "api_version" => "abc"
assert_equal "template v1", @response.body
end
Expand Down
34 changes: 15 additions & 19 deletions test/unit/configuration_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,48 +2,44 @@

class ConfigurationTest < ActiveSupport::TestCase
setup do
@previous_versions = VersionCake::Configuration.supported_version_numbers
end

teardown do
VersionCake::Configuration.supported_version_numbers = @previous_versions
@config = VersionCake::Configuration.new
end

test "supported_version_numbers can be set with range" do
VersionCake::Configuration.supported_version_numbers = (1..7)
assert_equal [7,6,5,4,3,2,1], VersionCake::Configuration.supported_version_numbers
@config.supported_version_numbers = (1..7)
assert_equal [7,6,5,4,3,2,1], @config.supported_version_numbers
end

test "supported_version_numbers can be set with an unordered array" do
VersionCake::Configuration.supported_version_numbers = [2,4,1,5,3,6,7]
assert_equal [7,6,5,4,3,2,1], VersionCake::Configuration.supported_version_numbers
@config.supported_version_numbers = [2,4,1,5,3,6,7]
assert_equal [7,6,5,4,3,2,1], @config.supported_version_numbers
end

test "supported_version_numbers can be set with a single value" do
VersionCake::Configuration.supported_version_numbers = 19
assert_equal [19], VersionCake::Configuration.supported_version_numbers
@config.supported_version_numbers = 19
assert_equal [19], @config.supported_version_numbers
end

test "supports_version? is only true for given supported versions" do
VersionCake::Configuration.supported_version_numbers = (1..7)
VersionCake::Configuration.supported_version_numbers.each do |supported_version|
assert VersionCake::Configuration.supports_version? supported_version
@config.supported_version_numbers = (1..7)
@config.supported_version_numbers.each do |supported_version|
assert @config.supports_version? supported_version
end
end

test "supports_version? is not true for other versions" do
VersionCake::Configuration.supported_version_numbers = (1..7)
@config.supported_version_numbers = (1..7)
[-2,-1,0,8,9,10].each do |unsupported_version|
assert !VersionCake::Configuration.supports_version?(unsupported_version)
assert !@config.supports_version?(unsupported_version)
end
end

test "latest_version retrieves the highest supported version" do
VersionCake::Configuration.supported_version_numbers = [4,1,3,9,2,54]
assert_equal 54, VersionCake::Configuration.latest_version
@config.supported_version_numbers = [4,1,3,9,2,54]
assert_equal 54, @config.latest_version
end

test "default supported_version_numbers should be a logic set of version numbers" do
assert_equal (1..10), VersionCake::Configuration::SUPPORTED_VERSIONS_DEFAULT
assert_equal (1..10).to_a.reverse, @config.supported_version_numbers
end
end
2 changes: 1 addition & 1 deletion test/unit/versioned_request_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class VersionedRequestTest < ActiveSupport::TestCase

test "a request for a deprecated version raises an exception" do
VersionCake::VersionedRequest.any_instance.stubs(:apply_strategies => 2)
VersionCake::Configuration.stubs(:supports_version? => false)
VersionCake::Configuration.any_instance.stubs(:supports_version? => false)
assert_raise ActionController::RoutingError do
VersionCake::VersionedRequest.new(stub())
end
Expand Down

0 comments on commit 4a5d2cd

Please sign in to comment.