Skip to content

Commit

Permalink
Merge branch 'feature-strategy_refactoring'
Browse files Browse the repository at this point in the history
  • Loading branch information
bwillis committed Apr 14, 2013
2 parents 71a51a6 + 39dd040 commit 65ccc3b
Show file tree
Hide file tree
Showing 19 changed files with 222 additions and 42 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
.idea
.rvmrc
.ruby-gemset
.ruby-version
spec/log
log/
*.gem
Expand Down
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ group :development do
# for travis-ci.org
gem "rake"
gem 'test-unit'
gem 'mocha', '~> 0.12.0', :require => false
end
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ DEPENDENCIES
activerecord
coveralls
i18n (= 0.6.1)
mocha
mocha (~> 0.12.0)
multi_json
rack
rake
Expand Down
7 changes: 7 additions & 0 deletions lib/versioncake.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
require 'versioncake/strategies/extraction_strategy'
require 'versioncake/strategies/http_accept_parameter_strategy'
require 'versioncake/strategies/http_header_strategy'
require 'versioncake/strategies/query_parameter_strategy'
require 'versioncake/strategies/request_parameter_strategy'
require 'versioncake/strategies/custom_strategy'

require 'versioncake/action_view/template'
require 'versioncake/action_view/versions'
require 'versioncake/action_view/lookup_context'
Expand Down
2 changes: 1 addition & 1 deletion lib/versioncake/action_view/railtie.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class ActionViewVersions < Rails::Railtie
end

if app.config.respond_to?(:view_version_string)
ActionView::Template::Versions.version_string = app.config.view_version_string
VersionCake::ExtractionStrategy.version_string = app.config.view_version_string
end
end
end
Expand Down
45 changes: 7 additions & 38 deletions lib/versioncake/action_view/versions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,56 +4,25 @@ module ActionView
class Template
module Versions

mattr_accessor :version_string
self.version_string = "api_version"

mattr_accessor :supported_version_numbers
self.supported_version_numbers = []

mattr_accessor :extraction_strategy
self.extraction_strategy = [:query_parameter]
mattr_accessor :extraction_strategies
self.extraction_strategies = [:query_parameter]

def self.extract_version(request)
version = nil
extraction_strategy.each do |strategy|
version = apply_strategy(request, strategy)
extraction_strategies.each do |strategy|
version = strategy.extract(request)
break unless version.nil?
end
version
end

def self.apply_strategy(request, strategy)
case strategy
when Proc
strategy.call(request)
when :http_accept_parameter
if request.headers.has_key?("HTTP_ACCEPT") &&
match = request.headers["HTTP_ACCEPT"].match(%{#{@@version_string}=([0-9])})
match[1].to_i
end
when :http_header
if request.headers.has_key? "HTTP_X_#{@@version_string.upcase}"
request.headers["HTTP_X_#{@@version_string.upcase}"].to_i
end
when :query_parameter
if request.query_parameters.has_key? @@version_string.to_sym
request.query_parameters[@@version_string.to_sym].to_i
end
when :request_parameter
if request.request_parameters.has_key? @@version_string.to_sym
request.request_parameters[@@version_string.to_sym].to_i
end
else
raise "Unknown extraction strategy #{strategy}"
end
end

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

Expand Down
11 changes: 11 additions & 0 deletions lib/versioncake/strategies/custom_strategy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module VersionCake
class CustomStrategy < ExtractionStrategy
def initialize(callback)
@callback = callback
end

def execute(request)
@callback.call(request)
end
end
end
37 changes: 37 additions & 0 deletions lib/versioncake/strategies/extraction_strategy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
require 'active_support/core_ext/class/attribute_accessors.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
end

def execute(request)
raise Exception, "ExtractionStrategy requires execute to be implemented"
end

def self.lookup(strategy)
if strategy.class == Proc
if strategy.arity == 1
VersionCake::CustomStrategy.new(strategy)
else
raise Exception, "Custom extraction strategy requires a single parameter"
end
else
strategy_name = "#{strategy}_strategy".camelize
begin
VersionCake.const_get(strategy_name).new
rescue
raise Exception, "Unknown VersionCake extraction strategy #{strategy_name}"
end
end

end

end
end
12 changes: 12 additions & 0 deletions lib/versioncake/strategies/http_accept_parameter_strategy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module VersionCake
class HttpAcceptParameterStrategy < ExtractionStrategy

def execute(request)
if request.headers.has_key?("HTTP_ACCEPT") &&
match = request.headers["HTTP_ACCEPT"].match(/#{@@version_string}=([0-9]+)/)
match[1]
end
end

end
end
11 changes: 11 additions & 0 deletions lib/versioncake/strategies/http_header_strategy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module VersionCake
class HttpHeaderStrategy < ExtractionStrategy

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

end
end
11 changes: 11 additions & 0 deletions lib/versioncake/strategies/query_parameter_strategy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module VersionCake
class QueryParameterStrategy < ExtractionStrategy

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

end
end
11 changes: 11 additions & 0 deletions lib/versioncake/strategies/request_parameter_strategy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
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].to_i
end
end

end
end
4 changes: 2 additions & 2 deletions test/functional/renders_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ class RendersControllerTest < ActionController::TestCase

setup do
# change the version string for configuration testing
ActionView::Template::Versions.version_string = "version"
VersionCake::ExtractionStrategy.version_string = "version"
end

teardown do
ActionView::Template::Versions.version_string = "api_version"
VersionCake::ExtractionStrategy.version_string = "api_version"
end

test "render latest version of partial" do
Expand Down
2 changes: 2 additions & 0 deletions test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
require 'rails/test_help'
require 'test/unit'

require "mocha"

require File.expand_path('../config/application', __FILE__)

FIXTURE_LOAD_PATH = File.join(File.dirname(__FILE__), 'fixtures')
Expand Down
38 changes: 38 additions & 0 deletions test/unit/extraction_strategy_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
require './test/test_helper'

class ExtractionStrategyTest < ActiveSupport::TestCase
test "execute is required for a strategy" do
assert_raise(Exception) do
VersionCake::ExtractionStrategy.new.execute("request")
end
end

test "extract will convert the the result to integer" do
class TestStrategy < VersionCake::ExtractionStrategy
def execute(request); "123"; end
end
assert_equal TestStrategy.new.extract("request"), 123
end

test "it can lookup a strategy" do
strategy = VersionCake::ExtractionStrategy.lookup(:query_parameter)
assert_equal VersionCake::QueryParameterStrategy, strategy.class
end

test "it creates a custom strategy for a proc" do
strategy = VersionCake::ExtractionStrategy.lookup(lambda{|req|})
assert_equal VersionCake::CustomStrategy, strategy.class
end

test "it fails to create a custom strategy for a proc with no parameters" do
assert_raise(Exception) do
VersionCake::ExtractionStrategy.lookup(lambda{})
end
end

test "it raises error when no strategy is found" do
assert_raise(Exception) do
VersionCake::ExtractionStrategy.lookup(:fake_extraction)
end
end
end
17 changes: 17 additions & 0 deletions test/unit/http_accept_parameter_strategy_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
require './test/test_helper'

class HttpAcceptParameterStrategyTest < ActiveSupport::TestCase
setup do
@strategy = VersionCake::HttpAcceptParameterStrategy.new
end

test "a request with an HTTP_ACCEPT version retrieves the version" do
request = stub(:headers => {'HTTP_ACCEPT' => 'application/xml; api_version=11'})
assert_equal 11, @strategy.extract(request)
end

test "a request without an HTTP_ACCEPT version returns nil" do
request = stub(:headers => {'HTTP_ACCEPT' => 'text/x-dvi; q=.8; mxb=100000; mxt=5.0, text/x-c'})
assert_nil @strategy.extract(request)
end
end
17 changes: 17 additions & 0 deletions test/unit/http_header_strategy_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
require './test/test_helper'

class HttpHeaderStrategyTest < ActiveSupport::TestCase
setup do
@strategy = VersionCake::HttpHeaderStrategy.new
end

test "a request with an HTTP_X_API_VERSION retrieves the version" do
request = stub(:headers => {'HTTP_X_API_VERSION' => '11'})
assert_equal 11, @strategy.extract(request)
end

test "a request without an HTTP_X_API_VERSION returns nil" do
request = stub(:headers => {'HTTP_ACCEPT' => 'text/x-dvi; q=.8; mxb=100000; mxt=5.0, text/x-c'})
assert_nil @strategy.extract(request)
end
end
17 changes: 17 additions & 0 deletions test/unit/query_parameter_strategy_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
require './test/test_helper'

class QueryParameterStrategyTest < ActiveSupport::TestCase
setup do
@strategy = VersionCake::QueryParameterStrategy.new
end

test "a request with an api_version parameter retrieves the version" do
request = stub(:query_parameters => {:api_version => '11', :other => 'parameter'})
assert_equal 11, @strategy.extract(request)
end

test "a request without an api_version parameter returns nil" do
request = stub(:query_parameters => {:other => 'parameter', :another => 'parameter'})
assert_nil @strategy.extract(request)
end
end
17 changes: 17 additions & 0 deletions test/unit/request_parameter_strategy_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
require './test/test_helper'

class RequestParameterStrategyTest < ActiveSupport::TestCase
setup do
@strategy = VersionCake::RequestParameterStrategy.new
end

test "a request with an api_version request parameter retrieves the version" do
request = stub(:request_parameters => {:api_version => '11', :other => 'parameter'})
assert_equal 11, @strategy.extract(request)
end

test "a request without an api_version request parameter returns nil" do
request = stub(:request_parameters => {:other => 'parameter', :another => 'parameter'})
assert_nil @strategy.extract(request)
end
end

0 comments on commit 65ccc3b

Please sign in to comment.