versioncake 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. data/.gitignore +4 -0
  2. data/.travis.yml +4 -0
  3. data/Gemfile +17 -0
  4. data/Gemfile.lock +97 -0
  5. data/README.md +76 -0
  6. data/Rakefile +31 -0
  7. data/lib/versioncake/action_controller/versioning.rb +26 -0
  8. data/lib/versioncake/action_view/lookup_context.rb +10 -0
  9. data/lib/versioncake/action_view/railtie.rb +15 -0
  10. data/lib/versioncake/action_view/resolver.rb +13 -0
  11. data/lib/versioncake/action_view/template.rb +11 -0
  12. data/lib/versioncake/action_view/versions.rb +88 -0
  13. data/lib/versioncake/version.rb +3 -0
  14. data/lib/versioncake.rb +6 -0
  15. data/spec/app/controllers/renders_controller.rb +4 -0
  16. data/spec/app/views/renders/index.html.erb +1 -0
  17. data/spec/app/views/renders/index.v1.html.erb +1 -0
  18. data/spec/app/views/renders/index.v2.html.erb +1 -0
  19. data/spec/config/application.rb +13 -0
  20. data/spec/config/database.yml +4 -0
  21. data/spec/config/routes.rb +3 -0
  22. data/spec/config.ru +0 -0
  23. data/spec/db/test.sqlite3 +0 -0
  24. data/spec/fixtures/partials/_versioned.erb +1 -0
  25. data/spec/fixtures/partials/_versioned.v1.erb +1 -0
  26. data/spec/fixtures/partials/_versioned.v2.erb +1 -0
  27. data/spec/fixtures/partials/_versioned.v3.erb +1 -0
  28. data/spec/fixtures/partials/another_versioned_partial.erb +1 -0
  29. data/spec/fixtures/partials/another_versioned_partial.v1.erb +1 -0
  30. data/spec/fixtures/templates/unversioned.html.erb +1 -0
  31. data/spec/fixtures/templates/versioned.html.erb +1 -0
  32. data/spec/fixtures/templates/versioned.v1.html.erb +1 -0
  33. data/spec/fixtures/templates/versioned.v2.html.erb +1 -0
  34. data/spec/fixtures/templates/versioned.v3.html.erb +1 -0
  35. data/spec/script/rails +0 -0
  36. data/spec/spec_helper.rb +27 -0
  37. data/spec/template/render_spec.rb +34 -0
  38. data/spec/template/resolver_spec.rb +12 -0
  39. data/test/app/controllers/renders_controller.rb +7 -0
  40. data/test/app/views/renders/index.html.erb +1 -0
  41. data/test/app/views/renders/index.v1.html.erb +1 -0
  42. data/test/app/views/renders/index.v2.html.erb +1 -0
  43. data/test/config/application.rb +15 -0
  44. data/test/config/database.yml +4 -0
  45. data/test/config/routes.rb +3 -0
  46. data/test/config.ru +0 -0
  47. data/test/db/test.sqlite3 +0 -0
  48. data/test/functional/renders_controller_test.rb +145 -0
  49. data/test/script/rails +0 -0
  50. data/test/test_helper.rb +32 -0
  51. data/versioncake.gemspec +23 -0
  52. metadata +166 -0
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ .idea
2
+ .rvmrc
3
+ spec/log
4
+ log/
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.2
4
+ - 1.9.3
data/Gemfile ADDED
@@ -0,0 +1,17 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ gem 'rack'
6
+ gem 'actionpack'
7
+ gem 'activerecord'
8
+ gem 'multi_json'
9
+ gem 'i18n', '0.6.1'
10
+ gem 'tzinfo'
11
+ gem 'sqlite3'
12
+
13
+ group :development do
14
+ # for travis-ci.org
15
+ gem "rake"
16
+ gem 'test-unit'
17
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,97 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ versioncake (0.1.0)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+ actionpack (3.2.8)
10
+ activemodel (= 3.2.8)
11
+ activesupport (= 3.2.8)
12
+ builder (~> 3.0.0)
13
+ erubis (~> 2.7.0)
14
+ journey (~> 1.0.4)
15
+ rack (~> 1.4.0)
16
+ rack-cache (~> 1.2)
17
+ rack-test (~> 0.6.1)
18
+ sprockets (~> 2.1.3)
19
+ activemodel (3.2.8)
20
+ activesupport (= 3.2.8)
21
+ builder (~> 3.0.0)
22
+ activerecord (3.2.8)
23
+ activemodel (= 3.2.8)
24
+ activesupport (= 3.2.8)
25
+ arel (~> 3.0.2)
26
+ tzinfo (~> 0.3.29)
27
+ activesupport (3.2.8)
28
+ i18n (~> 0.6)
29
+ multi_json (~> 1.0)
30
+ arel (3.0.2)
31
+ builder (3.0.0)
32
+ diff-lcs (1.1.3)
33
+ erubis (2.7.0)
34
+ hike (1.2.1)
35
+ i18n (0.6.1)
36
+ journey (1.0.4)
37
+ json (1.7.5)
38
+ metaclass (0.0.1)
39
+ mocha (0.12.3)
40
+ metaclass (~> 0.0.1)
41
+ multi_json (1.3.6)
42
+ rack (1.4.1)
43
+ rack-cache (1.2)
44
+ rack (>= 0.4)
45
+ rack-ssl (1.3.2)
46
+ rack
47
+ rack-test (0.6.1)
48
+ rack (>= 1.0)
49
+ railties (3.2.8)
50
+ actionpack (= 3.2.8)
51
+ activesupport (= 3.2.8)
52
+ rack-ssl (~> 1.3.2)
53
+ rake (>= 0.8.7)
54
+ rdoc (~> 3.4)
55
+ thor (>= 0.14.6, < 2.0)
56
+ rake (0.9.2.2)
57
+ rdoc (3.12)
58
+ json (~> 1.4)
59
+ rspec (2.11.0)
60
+ rspec-core (~> 2.11.0)
61
+ rspec-expectations (~> 2.11.0)
62
+ rspec-mocks (~> 2.11.0)
63
+ rspec-core (2.11.1)
64
+ rspec-expectations (2.11.2)
65
+ diff-lcs (~> 1.1.3)
66
+ rspec-mocks (2.11.2)
67
+ rspec-rails (2.11.0)
68
+ actionpack (>= 3.0)
69
+ activesupport (>= 3.0)
70
+ railties (>= 3.0)
71
+ rspec (~> 2.11.0)
72
+ sprockets (2.1.3)
73
+ hike (~> 1.2)
74
+ rack (~> 1.0)
75
+ tilt (~> 1.1, != 1.3.0)
76
+ sqlite3 (1.3.6)
77
+ test-unit (2.5.2)
78
+ thor (0.16.0)
79
+ tilt (1.3.3)
80
+ tzinfo (0.3.33)
81
+
82
+ PLATFORMS
83
+ ruby
84
+
85
+ DEPENDENCIES
86
+ actionpack
87
+ activerecord
88
+ i18n (= 0.6.1)
89
+ mocha
90
+ multi_json
91
+ rack
92
+ rake
93
+ rspec-rails
94
+ sqlite3
95
+ test-unit
96
+ tzinfo
97
+ versioncake!
data/README.md ADDED
@@ -0,0 +1,76 @@
1
+ # Version Cake [![Build Status](https://secure.travis-ci.org/bwillis/versioncake.png?branch=master)](http://travis-ci.org/bwillis/versioncake)
2
+
3
+ Version Cake is a way to easily version views in your Rails app.
4
+
5
+ ## Install - not release yet
6
+
7
+ ```
8
+ gem install versioncake
9
+ ```
10
+
11
+ ## How to use
12
+
13
+ ### Configure
14
+
15
+ You need to define the supported versions in your Rails application.rb file as
16
+ ```view_versions```. Use this config to set the range of supported API
17
+ versions that can be served:
18
+
19
+ ```ruby
20
+ config.view_versions = [1,3,4,5] # or (1...5)
21
+ #config.view_version_extraction_strategy = :http_parameter # options = :http_header, :http_accept_parameter, :query_parameter, custom Proc
22
+ ```
23
+
24
+ ### Version your views
25
+
26
+ When a client makes a request to your controller the latest version of the
27
+ view will be rendered. The latest version is determined by naming the template
28
+ or partial with a version number that you configured to support.
29
+
30
+ ```
31
+ - app/views/posts
32
+ - index.html.erb
33
+ - edit.html.erb
34
+ - show.html.erb
35
+ - show.json.jbuilder
36
+ - show.v1.json.jbuilder
37
+ - show.v2.json.jbuilder
38
+ - new.html.erb
39
+ - _form.html.erb
40
+ ```
41
+
42
+ If you start supporting a newer version, v3 for instance, a request for the latest
43
+ version of posts/show will gracefully degrade to the latest support available
44
+ version, in this case posts/show.v2.json.jbuilder.
45
+
46
+ ### Client requests
47
+
48
+ When a client makes a request it will automatically receive the latest supported
49
+ version of the view. The client can also request for a specific version by one of three
50
+ strategies configured by ``view_version_extraction_strategy``:
51
+
52
+ - http_header: Api version HTTP header ie. ```API-Version: 1```
53
+ - http_accept_parameter: HTTP Accept header ie. ```Accept: application/xml; version=1```
54
+ - http://blog.steveklabnik.com/posts/2011-07-03-nobody-understands-rest-or-http#i_want_my_api_to_be_versioned
55
+ - query_parameter: version in the url query parameter ie. ```http://localhost:3000/posts.json?api_version=1```
56
+
57
+ A custom strategy is available by providing a proc to the ``view_version_extraction_strategy`` configuration. It
58
+ takes a single parameter of the current request and must return an integer.
59
+
60
+ ```ruby
61
+ Proc.new { |request| request.headers["HTTP_X_API_MAGIC"].to_i }
62
+ ```
63
+
64
+ ## Development Work
65
+
66
+ 1. Finish convertion of Rspec tests to TestUnit
67
+ 2. Syntatic sugar controller helpers to detect the version - interface discussion: https://github.com/bwillis/versioncake/commit/3dbdaf612ff99676c499a456f3e858e22382e76b#commitcomment-1847368
68
+ 3. Log the version requested in the logs
69
+
70
+ # Similar Libraries
71
+
72
+ - https://github.com/bploetz/versionist
73
+
74
+ # License
75
+
76
+ Version Cake is released under the MIT license: www.opensource.org/licenses/MIT
data/Rakefile ADDED
@@ -0,0 +1,31 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rake/dsl_definition'
4
+ require "bundler"
5
+ Bundler.setup
6
+
7
+ require "rspec"
8
+ require "rspec/core/rake_task"
9
+ require 'rake/testtask'
10
+
11
+ $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
12
+
13
+ Bundler::GemHelper.install_tasks
14
+
15
+ task :default => :spec
16
+
17
+ RSpec::Core::RakeTask.new(:spec) do |spec|
18
+ spec.pattern = 'spec/**/*_spec.rb'
19
+ end
20
+
21
+ $: << "."
22
+ $: << "./test"
23
+
24
+ Rake::TestTask.new do |i|
25
+ #i.libs << '.'
26
+ i.libs << 'test'
27
+ i.test_files = FileList['test/**/*_test.rb']
28
+ #i.test_files = FileList['test/test_*.rb']
29
+ #i.test_files = FileList.new('test/**/*_test.rb')
30
+ i.verbose = true
31
+ end
@@ -0,0 +1,26 @@
1
+ require 'action_controller'
2
+
3
+ module ActionController #:nodoc:
4
+ module Versioning
5
+ extend ActiveSupport::Concern
6
+
7
+ attr_accessor :requested_version, :is_latest_version
8
+
9
+ included do
10
+ prepend_before_filter :set_version
11
+ end
12
+
13
+ protected
14
+ def set_version
15
+ requested_version = ActionView::Template::Versions.extract_version request
16
+ if ActionView::Template::Versions.supports_version? requested_version
17
+ @requested_version = requested_version
18
+ @_lookup_context.versions = ActionView::Template::Versions.supported_versions(requested_version)
19
+ else
20
+ @requested_version = ActionView::Template::Versions.latest_version
21
+ end
22
+ @is_latest_version = @requested_version == ActionView::Template::Versions.latest_version
23
+ end
24
+ end
25
+ end
26
+ ActionController::Base.send(:include, ActionController::Versioning)
@@ -0,0 +1,10 @@
1
+ require 'action_view'
2
+
3
+ ActionView::LookupContext.class_eval do
4
+
5
+ # register an addition detail for the lookup context to understand,
6
+ # this will allow us to have the versions available upon lookup in
7
+ # the resolver.
8
+ register_detail(:versions){ ActionView::Template::Versions.supported_versions }
9
+
10
+ end
@@ -0,0 +1,15 @@
1
+ require 'rails'
2
+
3
+ class ActionViewVersions < Rails::Railtie
4
+ initializer "view_versions" do |app|
5
+ ActiveSupport.on_load(:action_view) do
6
+ if app.config.respond_to?(:view_versions)
7
+ ActionView::Template::Versions.supported_version_numbers = app.config.view_versions
8
+ end
9
+
10
+ if app.config.respond_to?(:view_version_extraction_strategy)
11
+ ActionView::Template::Versions.extraction_strategy = app.config.view_version_extraction_strategy
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,13 @@
1
+ require 'action_view'
2
+
3
+ ActionView::PathResolver.class_eval do
4
+
5
+ # not sure why we are doing this yet, but looks like a good idea
6
+ ActionView::PathResolver::EXTENSIONS.replace [:locale, :versions, :formats, :handlers]
7
+
8
+ # The query builder has the @details from the lookup_context and will
9
+ # match the detail name to the string in the pattern, so we must append
10
+ # it to the default pattern
11
+ ActionView::PathResolver::DEFAULT_PATTERN.replace ":prefix/:action{.:locale,}{.:versions,}{.:formats,}{.:handlers,}"
12
+
13
+ end
@@ -0,0 +1,11 @@
1
+ require 'action_view'
2
+
3
+ ActionView::Template.class_eval do
4
+
5
+ # the identifier method name filters out numbers,
6
+ # but we want to preserve them for v1 etc.
7
+ def identifier_method_name #:nodoc:
8
+ inspect.gsub(/[^a-z0-9_]/, '_')
9
+ end
10
+
11
+ end
@@ -0,0 +1,88 @@
1
+ require 'active_support/core_ext/module/attribute_accessors.rb'
2
+
3
+ module ActionView
4
+ class Template
5
+ module Versions
6
+
7
+ VERSION_STRING = "api_version"
8
+
9
+ mattr_accessor :supported_version_numbers
10
+ self.supported_version_numbers = []
11
+
12
+ mattr_accessor :extraction_strategy
13
+ self.extraction_strategy = [:query_parameter]
14
+
15
+ EXTRACTION_STRATEGIES = {
16
+ :query_parameter => lambda { |request|
17
+ if request.query_parameters.has_key? VERSION_STRING.to_sym
18
+ request.query_parameters[VERSION_STRING.to_sym].to_i
19
+ end
20
+ },
21
+ :http_header => lambda { |request|
22
+ if request.headers.has_key? "HTTP_#{VERSION_STRING.upcase}"
23
+ request.headers["HTTP_#{VERSION_STRING.upcase}"].to_i
24
+ end
25
+ },
26
+ :http_accept_parameter => lambda { |request|
27
+ if request.headers.has_key?("HTTP_ACCEPT") &&
28
+ match = request.headers["HTTP_ACCEPT"].match(%{#{VERSION_STRING}=([0-9])})
29
+ match[1].to_i
30
+ end
31
+ }
32
+ }
33
+
34
+ def self.extract_version(request)
35
+ version = nil
36
+ extraction_strategy.each do |strategy|
37
+ version = if strategy.is_a? Proc
38
+ strategy.call(request)
39
+ elsif EXTRACTION_STRATEGIES.include? strategy
40
+ EXTRACTION_STRATEGIES[strategy].call(request)
41
+ else
42
+ raise "Unknown extraction strategy #{strategy}"
43
+ end
44
+ break unless version.nil?
45
+ end
46
+ version
47
+ end
48
+
49
+ def self.extraction_strategy=(val)
50
+ case val
51
+ when Array
52
+ @@extraction_strategy = val
53
+ else
54
+ @@extraction_strategy = Array.wrap(val)
55
+ end
56
+ end
57
+
58
+ def self.supported_version_numbers=(val)
59
+ case val
60
+ when Range
61
+ @@supported_version_numbers = val.to_a
62
+ when Array
63
+ @@supported_version_numbers = val
64
+ else
65
+ @@supported_version_numbers = Array.wrap(val)
66
+ end
67
+ @@supported_version_numbers.reverse!
68
+ end
69
+
70
+ def self.supported_versions(requested_version_number=nil)
71
+ supported_version_numbers.collect do |supported_version_number|
72
+ if requested_version_number.nil? || supported_version_number <= requested_version_number
73
+ :"v#{supported_version_number}"
74
+ end
75
+ end
76
+ end
77
+
78
+ def self.supports_version?(version)
79
+ supported_version_numbers.include? version
80
+ end
81
+
82
+ def self.latest_version
83
+ supported_version_numbers.first
84
+ end
85
+
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,3 @@
1
+ module VersionCake
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,6 @@
1
+ require 'versioncake/action_view/template'
2
+ require 'versioncake/action_view/versions'
3
+ require 'versioncake/action_view/lookup_context'
4
+ require 'versioncake/action_view/resolver'
5
+ require 'versioncake/action_controller/versioning'
6
+ require 'versioncake/action_view/railtie'
@@ -0,0 +1,4 @@
1
+ class RendersController < ActionController::Base
2
+ def index
3
+ end
4
+ end
@@ -0,0 +1 @@
1
+ index.html.erb
@@ -0,0 +1 @@
1
+ index.v1.html.erb
@@ -0,0 +1 @@
1
+ index.v2.html.erb
@@ -0,0 +1,13 @@
1
+ module RendersTest
2
+ class Application < Rails::Application
3
+ config.encoding = "utf-8"
4
+ config.filter_parameters += [:password]
5
+ config.active_support.escape_html_entities_in_json = true
6
+ config.active_record.whitelist_attributes = true
7
+ config.assets.enabled = true
8
+ config.assets.version = '1.0'
9
+ config.active_support.deprecation = :stderr
10
+ config.view_versions = (1..4)
11
+ config.view_version_extraction_strategy = :http_header
12
+ end
13
+ end
@@ -0,0 +1,4 @@
1
+ test:
2
+ adapter: sqlite3
3
+ database: db/test.sqlite3
4
+ timeout: 5000
@@ -0,0 +1,3 @@
1
+ RendersTest::Application.routes.draw do
2
+ resources :renders
3
+ end
data/spec/config.ru ADDED
File without changes
File without changes
@@ -0,0 +1 @@
1
+ partial
@@ -0,0 +1 @@
1
+ partial version 1
@@ -0,0 +1 @@
1
+ partial base
@@ -0,0 +1 @@
1
+ partial version 3
@@ -0,0 +1 @@
1
+ another versioned partial
@@ -0,0 +1 @@
1
+ another versioned partial v1
@@ -0,0 +1 @@
1
+ unversioned template
@@ -0,0 +1 @@
1
+ template
@@ -0,0 +1 @@
1
+ template v1
@@ -0,0 +1 @@
1
+ template v2
@@ -0,0 +1 @@
1
+ template v3
data/spec/script/rails ADDED
File without changes
@@ -0,0 +1,27 @@
1
+ require 'bundler'
2
+ Bundler.require
3
+
4
+ require 'versioncake'
5
+ require 'rspec'
6
+ require 'rails/all'
7
+ require 'rspec/rails'
8
+ require 'config/application'
9
+
10
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
11
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
12
+
13
+ ENV["RAILS_ENV"] ||= 'test'
14
+
15
+ root = File.expand_path(File.dirname(__FILE__))
16
+
17
+ # Initialize the application
18
+ RendersTest::Application.initialize!
19
+
20
+ RSpec.configure do |config|
21
+ config.mock_with :mocha
22
+ end
23
+
24
+ FIXTURE_LOAD_PATH = File.join(File.dirname(__FILE__), 'fixtures')
25
+ FIXTURES = Pathname.new(FIXTURE_LOAD_PATH)
26
+
27
+ Dir.glob(File.dirname(__FILE__) + "/app/controllers/**/*").each{|f| require(f) if File.file?(f)}
@@ -0,0 +1,34 @@
1
+ require "spec_helper"
2
+
3
+ describe "RenderTestCases" do
4
+
5
+ before do
6
+ path = ActionView::FileSystemResolver.new(FIXTURE_LOAD_PATH)
7
+ view_paths = ActionView::PathSet.new([path])
8
+ @view = ActionView::Base.new(view_paths,{})
9
+ end
10
+
11
+ it "renders the unversioned template (regression)" do
12
+ @view.lookup_context.versions = [:v0]
13
+ @view.render(:template => "templates/versioned").should == "template"
14
+ end
15
+
16
+ it "renders the latest version of the template" do
17
+ @view.render(:template => "templates/versioned").should == "template v3"
18
+ end
19
+
20
+ it "renders the overridden version of the template" do
21
+ @view.render(:template => "templates/versioned", :versions => :v1).should == "template v1"
22
+ end
23
+
24
+ it "renders the legacy version of the template" do
25
+ @view.lookup_context.versions = [:v2]
26
+ @view.render(:template => "templates/versioned").should == "template v2"
27
+ end
28
+
29
+ it "renders the latest available version of the requested template" do
30
+ @view.lookup_context.versions = [:v4,:v3,:v2,:v1]
31
+ @view.render(:template => "templates/versioned").should == "template v3"
32
+ end
33
+
34
+ end
@@ -0,0 +1,12 @@
1
+ require "spec_helper"
2
+
3
+ describe "Resolver" do
4
+
5
+ it "extracts the correct handler and format from a versioned template" do
6
+ resolver = ActionView::PathResolver.new
7
+ handler, format = resolver.send "extract_handler_and_format", "/some/path/to/app/views/index.v1.xml.builder", nil
8
+ handler.class.should == ActionView::Template::Handlers::Builder
9
+ format.should == "application/xml"
10
+ end
11
+
12
+ end
@@ -0,0 +1,7 @@
1
+ require "action_controller"
2
+ require "action_controller/base"
3
+
4
+ class RendersController < ActionController::Base
5
+ def index
6
+ end
7
+ end
@@ -0,0 +1 @@
1
+ index.html.erb
@@ -0,0 +1 @@
1
+ index.v1.html.erb
@@ -0,0 +1 @@
1
+ index.v2.html.erb
@@ -0,0 +1,15 @@
1
+ require 'rails/all'
2
+
3
+ module RendersTest
4
+ class Application < Rails::Application
5
+ config.encoding = "utf-8"
6
+ config.filter_parameters += [:password]
7
+ config.active_support.escape_html_entities_in_json = true
8
+ config.active_record.whitelist_attributes = true
9
+ config.assets.enabled = true
10
+ config.assets.version = '1.0'
11
+ config.active_support.deprecation = :stderr
12
+ config.view_versions = (1..3)
13
+ config.view_version_extraction_strategy = :http_header
14
+ end
15
+ end
@@ -0,0 +1,4 @@
1
+ test:
2
+ adapter: sqlite3
3
+ database: db/test.sqlite3
4
+ timeout: 5000
@@ -0,0 +1,3 @@
1
+ RendersTest::Application.routes.draw do
2
+ resources :renders
3
+ end
data/test/config.ru ADDED
File without changes
File without changes
@@ -0,0 +1,145 @@
1
+ require 'test_helper'
2
+
3
+ require "action_controller"
4
+ require "action_controller/test_case"
5
+
6
+ class RendersControllerTest < ActionController::TestCase
7
+ test "render latest version of partial" do
8
+ get :index
9
+ assert_equal @response.body, "index.v2.html.erb"
10
+ end
11
+
12
+ test "exposes the requested version" do
13
+ get :index, "api_version" => "1"
14
+ assert_equal @controller.requested_version, 1
15
+ end
16
+
17
+ test "exposes latest version when requesting the latest" do
18
+ get :index, "api_version" => "4"
19
+ assert @controller.is_latest_version
20
+ end
21
+
22
+ test "reports not the latest version" do
23
+ get :index, "api_version" => "1"
24
+ assert !@controller.is_latest_version
25
+ end
26
+ end
27
+
28
+ class ParameterStragegyTest < ActionController::TestCase
29
+ tests RendersController
30
+
31
+ setup do
32
+ ActionView::Template::Versions.extraction_strategy = :query_parameter
33
+ end
34
+
35
+ test "render version 1 of the partial based on the parameter _api_version" do
36
+ get :index, "api_version" => "1"
37
+ assert_equal @response.body, "index.v1.html.erb"
38
+ end
39
+
40
+ test "render version 2 of the partial based on the parameter _api_version" do
41
+ get :index, "api_version" => "2"
42
+ assert_equal @response.body, "index.v2.html.erb"
43
+ end
44
+
45
+ test "render the latest available version (v2) of the partial based on the parameter _api_version" do
46
+ get :index, "api_version" => "3"
47
+ assert_equal @response.body, "index.v2.html.erb"
48
+ end
49
+ end
50
+
51
+ class CustomHeaderStrategyTest < ActionController::TestCase
52
+ tests RendersController
53
+
54
+ setup do
55
+ ActionView::Template::Versions.extraction_strategy = :http_header
56
+ end
57
+
58
+ test "renders version 1 of the partial based on the header API-Version" do
59
+ @controller.request.stubs(:headers).returns({"HTTP_API_VERSION" => "1"})
60
+ get :index
61
+ assert_equal @response.body, "index.v1.html.erb"
62
+ end
63
+
64
+ test "renders version 2 of the partial based on the header API-Version" do
65
+ @controller.request.stubs(:headers).returns({"HTTP_API_VERSION" => "2"})
66
+ get :index
67
+ assert_equal @response.body, "index.v2.html.erb"
68
+ end
69
+
70
+ test "renders the latest available version (v2) of the partial based on the header API-Version" do
71
+ @controller.request.stubs(:headers).returns({"HTTP_API_VERSION" => "3"})
72
+ get :index
73
+ assert_equal @response.body, "index.v2.html.erb"
74
+ end
75
+ end
76
+
77
+ class AcceptHeaderStrategyTest < ActionController::TestCase
78
+ tests RendersController
79
+
80
+ setup do
81
+ ActionView::Template::Versions.extraction_strategy = :http_accept_parameter
82
+ end
83
+
84
+ test "render version 1 of the partial based on the header Accept" do
85
+ @controller.request.stubs(:headers).returns({"HTTP_ACCEPT" => "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8;api_version=1"})
86
+ get :index
87
+ assert_equal @response.body, "index.v1.html.erb"
88
+ end
89
+
90
+ test "render version 2 of the partial based on the header Accept" do
91
+ @controller.request.stubs(:headers).returns({"HTTP_ACCEPT" => "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8;api_version=2"})
92
+ get :index
93
+ assert_equal @response.body, "index.v2.html.erb"
94
+ end
95
+
96
+ test "render the latest available version (v2) of the partial based on the header Accept" do
97
+ @controller.request.stubs(:headers).returns({"HTTP_ACCEPT" => "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8;api_version=3"})
98
+ get :index
99
+ assert_equal @response.body, "index.v2.html.erb"
100
+ end
101
+
102
+ test "render the latest version of the partial" do
103
+ @controller.request.stubs(:headers).returns({"HTTP_ACCEPT" => "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8;api_version=abc"})
104
+ get :index
105
+ assert_equal @response.body, "index.v2.html.erb"
106
+ end
107
+ end
108
+
109
+ class CustomStrategyTest < ActionController::TestCase
110
+ tests RendersController
111
+
112
+ setup do
113
+ ActionView::Template::Versions.extraction_strategy = lambda { |request| 2 }
114
+ end
115
+
116
+ test "renders version 2 of the partial based on the header Accept" do
117
+ get :index
118
+ assert_equal @response.body, "index.v2.html.erb"
119
+ end
120
+ end
121
+
122
+ class MultipleStrategyTest < ActionController::TestCase
123
+ tests RendersController
124
+
125
+ setup do
126
+ ActionView::Template::Versions.extraction_strategy = [:http_accept_parameter, :query_parameter]
127
+ end
128
+
129
+ test "renders version 1 of the partial based on the header Accept" do
130
+ @controller.request.stubs(:headers).returns({"HTTP_ACCEPT" => "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8;api_version=1"})
131
+ get :index
132
+ assert_equal @response.body, "index.v1.html.erb"
133
+ end
134
+
135
+ test "renders the query parameter when accept parameter isn't available" do
136
+ get :index, "api_version" => "1"
137
+ assert_equal @response.body, "index.v1.html.erb"
138
+ end
139
+
140
+ test "renders the higher priority accept parameter version" do
141
+ @controller.request.stubs(:headers).returns({"HTTP_ACCEPT" => "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8;api_version=2"})
142
+ get :index, "api_version" => "1"
143
+ assert_equal @response.body, "index.v2.html.erb"
144
+ end
145
+ end
data/test/script/rails ADDED
File without changes
@@ -0,0 +1,32 @@
1
+ require 'bundler'
2
+ Bundler.require
3
+
4
+ require 'versioncake'
5
+
6
+ ENV["RAILS_ENV"] = 'test'
7
+
8
+ require 'rails/all'
9
+ require 'rails/test_help'
10
+ require 'test/unit'
11
+
12
+
13
+ require File.expand_path('../config/application', __FILE__)
14
+
15
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
16
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
17
+
18
+ root = File.expand_path(File.dirname(__FILE__))
19
+
20
+ class ActiveSupport::TestCase
21
+ # Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
22
+ #
23
+ # Note: You'll currently still have to declare fixtures explicitly in integration tests
24
+ # -- they do not yet inherit this setting
25
+ fixtures :all
26
+
27
+ # Add more helper methods to be used by all tests here...
28
+ end
29
+
30
+ RendersTest::Application.initialize!
31
+
32
+ Dir.glob(File.dirname(__FILE__) + "/app/controllers/**/*").each{|f| require(f) if File.file?(f)}
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "versioncake/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "versioncake"
7
+ s.version = VersionCake::VERSION
8
+ s.authors = ["Jim Jones", "Ben Willis"]
9
+ s.email = ["jim.jones1@gmail.com", "benjamin.willis@gmail.com"]
10
+ s.homepage = "https://github.com/bwillis/versioncake"
11
+ s.summary = %q{Easily render versions of your rails views.}
12
+ s.description = %q{Render versioned views automagically based on the clients requested version.}
13
+
14
+ #s.rubyforge_project = ""
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_development_dependency "rspec-rails"
22
+ s.add_development_dependency "mocha"
23
+ end
metadata ADDED
@@ -0,0 +1,166 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: versioncake
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jim Jones
9
+ - Ben Willis
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2012-09-13 00:00:00.000000000Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rspec-rails
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ! '>='
29
+ - !ruby/object:Gem::Version
30
+ version: '0'
31
+ - !ruby/object:Gem::Dependency
32
+ name: mocha
33
+ requirement: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - ! '>='
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ type: :development
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ description: Render versioned views automagically based on the clients requested version.
48
+ email:
49
+ - jim.jones1@gmail.com
50
+ - benjamin.willis@gmail.com
51
+ executables: []
52
+ extensions: []
53
+ extra_rdoc_files: []
54
+ files:
55
+ - .gitignore
56
+ - .travis.yml
57
+ - Gemfile
58
+ - Gemfile.lock
59
+ - README.md
60
+ - Rakefile
61
+ - lib/versioncake.rb
62
+ - lib/versioncake/action_controller/versioning.rb
63
+ - lib/versioncake/action_view/lookup_context.rb
64
+ - lib/versioncake/action_view/railtie.rb
65
+ - lib/versioncake/action_view/resolver.rb
66
+ - lib/versioncake/action_view/template.rb
67
+ - lib/versioncake/action_view/versions.rb
68
+ - lib/versioncake/version.rb
69
+ - spec/app/controllers/renders_controller.rb
70
+ - spec/app/views/renders/index.html.erb
71
+ - spec/app/views/renders/index.v1.html.erb
72
+ - spec/app/views/renders/index.v2.html.erb
73
+ - spec/config.ru
74
+ - spec/config/application.rb
75
+ - spec/config/database.yml
76
+ - spec/config/routes.rb
77
+ - spec/db/test.sqlite3
78
+ - spec/fixtures/partials/_versioned.erb
79
+ - spec/fixtures/partials/_versioned.v1.erb
80
+ - spec/fixtures/partials/_versioned.v2.erb
81
+ - spec/fixtures/partials/_versioned.v3.erb
82
+ - spec/fixtures/partials/another_versioned_partial.erb
83
+ - spec/fixtures/partials/another_versioned_partial.v1.erb
84
+ - spec/fixtures/templates/unversioned.html.erb
85
+ - spec/fixtures/templates/versioned.html.erb
86
+ - spec/fixtures/templates/versioned.v1.html.erb
87
+ - spec/fixtures/templates/versioned.v2.html.erb
88
+ - spec/fixtures/templates/versioned.v3.html.erb
89
+ - spec/script/rails
90
+ - spec/spec_helper.rb
91
+ - spec/template/render_spec.rb
92
+ - spec/template/resolver_spec.rb
93
+ - test/app/controllers/renders_controller.rb
94
+ - test/app/views/renders/index.html.erb
95
+ - test/app/views/renders/index.v1.html.erb
96
+ - test/app/views/renders/index.v2.html.erb
97
+ - test/config.ru
98
+ - test/config/application.rb
99
+ - test/config/database.yml
100
+ - test/config/routes.rb
101
+ - test/db/test.sqlite3
102
+ - test/functional/renders_controller_test.rb
103
+ - test/script/rails
104
+ - test/test_helper.rb
105
+ - versioncake.gemspec
106
+ homepage: https://github.com/bwillis/versioncake
107
+ licenses: []
108
+ post_install_message:
109
+ rdoc_options: []
110
+ require_paths:
111
+ - lib
112
+ required_ruby_version: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ required_rubygems_version: !ruby/object:Gem::Requirement
119
+ none: false
120
+ requirements:
121
+ - - ! '>='
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ requirements: []
125
+ rubyforge_project:
126
+ rubygems_version: 1.8.19
127
+ signing_key:
128
+ specification_version: 3
129
+ summary: Easily render versions of your rails views.
130
+ test_files:
131
+ - spec/app/controllers/renders_controller.rb
132
+ - spec/app/views/renders/index.html.erb
133
+ - spec/app/views/renders/index.v1.html.erb
134
+ - spec/app/views/renders/index.v2.html.erb
135
+ - spec/config.ru
136
+ - spec/config/application.rb
137
+ - spec/config/database.yml
138
+ - spec/config/routes.rb
139
+ - spec/db/test.sqlite3
140
+ - spec/fixtures/partials/_versioned.erb
141
+ - spec/fixtures/partials/_versioned.v1.erb
142
+ - spec/fixtures/partials/_versioned.v2.erb
143
+ - spec/fixtures/partials/_versioned.v3.erb
144
+ - spec/fixtures/partials/another_versioned_partial.erb
145
+ - spec/fixtures/partials/another_versioned_partial.v1.erb
146
+ - spec/fixtures/templates/unversioned.html.erb
147
+ - spec/fixtures/templates/versioned.html.erb
148
+ - spec/fixtures/templates/versioned.v1.html.erb
149
+ - spec/fixtures/templates/versioned.v2.html.erb
150
+ - spec/fixtures/templates/versioned.v3.html.erb
151
+ - spec/script/rails
152
+ - spec/spec_helper.rb
153
+ - spec/template/render_spec.rb
154
+ - spec/template/resolver_spec.rb
155
+ - test/app/controllers/renders_controller.rb
156
+ - test/app/views/renders/index.html.erb
157
+ - test/app/views/renders/index.v1.html.erb
158
+ - test/app/views/renders/index.v2.html.erb
159
+ - test/config.ru
160
+ - test/config/application.rb
161
+ - test/config/database.yml
162
+ - test/config/routes.rb
163
+ - test/db/test.sqlite3
164
+ - test/functional/renders_controller_test.rb
165
+ - test/script/rails
166
+ - test/test_helper.rb