restful_route_version 0.0.2

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 (35) hide show
  1. data/Gemfile +11 -0
  2. data/Gemfile.lock +81 -0
  3. data/LICENSE +3 -0
  4. data/MIT-LICENSE +19 -0
  5. data/README.md +53 -0
  6. data/Rakefile +40 -0
  7. data/VERSION +1 -0
  8. data/lib/restful_route_version.rb +2 -0
  9. data/lib/restful_route_version/dependency_ext.rb +15 -0
  10. data/lib/restful_route_version/inherited_view_resolver.rb +26 -0
  11. data/lib/restful_route_version/railtie.rb +22 -0
  12. data/lib/restful_route_version/version_mapper.rb +109 -0
  13. data/restful_route_version.gemspec +99 -0
  14. data/test/dependency_ext_test.rb +50 -0
  15. data/test/fixture_files/a.rb +2 -0
  16. data/test/fixture_files/b.rb +2 -0
  17. data/test/fixture_files/c.rb +2 -0
  18. data/test/rails_sandbox/app/controllers/api/v10/articles_controller.rb +10 -0
  19. data/test/rails_sandbox/app/controllers/api/v10/notes_controller.rb +6 -0
  20. data/test/rails_sandbox/app/controllers/api/v10/questions_controller.rb +10 -0
  21. data/test/rails_sandbox/app/controllers/api/v10/songs_controller.rb +26 -0
  22. data/test/rails_sandbox/app/controllers/api/v11/articles_controller.rb +9 -0
  23. data/test/rails_sandbox/app/controllers/api/v11/tags_controller.rb +9 -0
  24. data/test/rails_sandbox/app/views/api/v10/songs/_bar.erb +1 -0
  25. data/test/rails_sandbox/app/views/api/v10/songs/create.html.erb +1 -0
  26. data/test/rails_sandbox/app/views/api/v10/songs/foo.html.erb +1 -0
  27. data/test/rails_sandbox/app/views/api/v10/songs/index.html.erb +1 -0
  28. data/test/rails_sandbox/app/views/api/v10/songs/show.html.erb +1 -0
  29. data/test/rails_sandbox/app/views/api/v11/songs/_wow.html.erb +1 -0
  30. data/test/rails_sandbox/app/views/api/v11/songs/bar.html.erb +1 -0
  31. data/test/rails_sandbox/app/views/api/v11/songs/baz.html.erb +1 -0
  32. data/test/rails_sandbox/app/views/api/v11/songs/show.html.erb +1 -0
  33. data/test/test_helper.rb +60 -0
  34. data/test/version_mapper_test.rb +201 -0
  35. metadata +158 -0
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "rails", "3.0.7"
4
+ gem "rake"
5
+
6
+ group :test do
7
+ gem "bundler", "~> 1.0.0"
8
+ gem "jeweler", "~> 1.5.2"
9
+ gem 'shoulda'
10
+ end
11
+
@@ -0,0 +1,81 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ abstract (1.0.0)
5
+ actionmailer (3.0.7)
6
+ actionpack (= 3.0.7)
7
+ mail (~> 2.2.15)
8
+ actionpack (3.0.7)
9
+ activemodel (= 3.0.7)
10
+ activesupport (= 3.0.7)
11
+ builder (~> 2.1.2)
12
+ erubis (~> 2.6.6)
13
+ i18n (~> 0.5.0)
14
+ rack (~> 1.2.1)
15
+ rack-mount (~> 0.6.14)
16
+ rack-test (~> 0.5.7)
17
+ tzinfo (~> 0.3.23)
18
+ activemodel (3.0.7)
19
+ activesupport (= 3.0.7)
20
+ builder (~> 2.1.2)
21
+ i18n (~> 0.5.0)
22
+ activerecord (3.0.7)
23
+ activemodel (= 3.0.7)
24
+ activesupport (= 3.0.7)
25
+ arel (~> 2.0.2)
26
+ tzinfo (~> 0.3.23)
27
+ activeresource (3.0.7)
28
+ activemodel (= 3.0.7)
29
+ activesupport (= 3.0.7)
30
+ activesupport (3.0.7)
31
+ arel (2.0.10)
32
+ builder (2.1.2)
33
+ erubis (2.6.6)
34
+ abstract (>= 1.0.0)
35
+ git (1.2.5)
36
+ i18n (0.5.0)
37
+ jeweler (1.5.2)
38
+ bundler (~> 1.0.0)
39
+ git (>= 1.2.5)
40
+ rake
41
+ mail (2.2.19)
42
+ activesupport (>= 2.3.6)
43
+ i18n (>= 0.4.0)
44
+ mime-types (~> 1.16)
45
+ treetop (~> 1.4.8)
46
+ mime-types (1.16)
47
+ polyglot (0.3.1)
48
+ rack (1.2.3)
49
+ rack-mount (0.6.14)
50
+ rack (>= 1.0.0)
51
+ rack-test (0.5.7)
52
+ rack (>= 1.0)
53
+ rails (3.0.7)
54
+ actionmailer (= 3.0.7)
55
+ actionpack (= 3.0.7)
56
+ activerecord (= 3.0.7)
57
+ activeresource (= 3.0.7)
58
+ activesupport (= 3.0.7)
59
+ bundler (~> 1.0)
60
+ railties (= 3.0.7)
61
+ railties (3.0.7)
62
+ actionpack (= 3.0.7)
63
+ activesupport (= 3.0.7)
64
+ rake (>= 0.8.7)
65
+ thor (~> 0.14.4)
66
+ rake (0.8.7)
67
+ shoulda (2.11.3)
68
+ thor (0.14.6)
69
+ treetop (1.4.9)
70
+ polyglot (>= 0.3.1)
71
+ tzinfo (0.3.27)
72
+
73
+ PLATFORMS
74
+ ruby
75
+
76
+ DEPENDENCIES
77
+ bundler (~> 1.0.0)
78
+ jeweler (~> 1.5.2)
79
+ rails (= 3.0.7)
80
+ rake
81
+ shoulda
data/LICENSE ADDED
@@ -0,0 +1,3 @@
1
+ Copyright (c) 2010 Hemant Kumar ( mail [at] gnufied [dot] org )
2
+
3
+ The Library is dual licensed under terms of Ruby License or MIT License.
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2010 Hemant Kumar ( mail [at] gnufied [dot] org )
2
+ Permission is hereby granted, free of charge, to any person obtaining
3
+ a copy of this software and associated documentation files (the
4
+ "Software"), to deal in the Software without restriction, including
5
+ without limitation the rights to use, copy, modify, merge, publish,
6
+ distribute, sublicense, and/or sell copies of the Software, and to
7
+ permit persons to whom the Software is furnished to do so, subject to
8
+ the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be
11
+ included in all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
14
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
15
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
17
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
18
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
19
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,53 @@
1
+ # Restful Route Version #
2
+
3
+ ### Useful for creating inheritable routes and controllers ###
4
+
5
+ Features
6
+ ----------
7
+
8
+ 1. It extends routing API of rails, letting us inherit routes between versions:
9
+
10
+ ```ruby
11
+ version_namespace :api do
12
+ version_namespace(:v10,:cache_route => true) do
13
+ resources :articles
14
+ resources :comments
15
+ resources :notes
16
+ end
17
+
18
+ version_namespace(:v11, :cache_route => true) do
19
+ inherit_routes("/api/v10", :except => %w(articles))
20
+ resources :articles
21
+ resources :tags
22
+ end
23
+
24
+ version_namespace(:v12) do
25
+ inherit_routes("/api/v11",:except => %w(notes))
26
+ resources :lessons
27
+ end
28
+ end
29
+ ```
30
+
31
+ Important thing to remember is only routes which were cached via `cache_route => true` can be
32
+ reused for inheritance. Normal namespace blocks aren't cached.
33
+
34
+ 2. Dynamically defines controllers between versions. In other words if v11 inherits 'notes' route
35
+ from v10, and v11 doesn't have its own NotesController defined the, plugin will
36
+ automatically define `Api::V11::NotesController` which will inherit from `Api::V10::NotesController`.
37
+
38
+
39
+ 3. Inherits view files (such as index.xml.builder) between versions. For example if `V11::ArticlesController`
40
+ inherits `V10::ArticlesController` it will as well inherit all the view files of `v10/articles/`
41
+ and hence there won't be any need to copy the view files around when creating new version of the API.
42
+
43
+
44
+ Template inheritance will work out of box on Rails 3.1, but if you are still on 3.0.x series,
45
+ you can use it now :
46
+
47
+ ```ruby
48
+ class Api::V10::BaseController < ActionController::Base
49
+ restful_route_version
50
+ end
51
+ ```
52
+
53
+ 4. Works with Ruby 1.9.2 and Ruby 1.8.7
@@ -0,0 +1,40 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ desc "Run tests"
4
+ task :test do
5
+ test_files = Dir["test/*_test.rb"]
6
+ $:.unshift(File.dirname(__FILE__)) unless
7
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
8
+ test_files.each { |x| load(x) }
9
+ end
10
+
11
+
12
+ begin
13
+ gem 'jeweler', '~> 1.4'
14
+ require 'jeweler'
15
+
16
+ Jeweler::Tasks.new do |gem|
17
+ gem.name = 'restful_route_version'
18
+ gem.summary = 'Versioning your routes in Rails3'
19
+ gem.description = 'Versioning your routes in Rails3'
20
+ gem.email = 'gethemant@gmail.com'
21
+
22
+ gem.homepage = 'http://github.com/gnufied/%s' % gem.name
23
+
24
+ gem.authors = [ 'Hemant Kumar']
25
+
26
+ gem.rubyforge_project = 'restful_route_version'
27
+
28
+ gem.add_dependency 'activesupport', '~> 3.0.0'
29
+ gem.add_dependency 'actionpack', '~> 3.0.0'
30
+ gem.add_dependency 'railties', '~> 3.0.0'
31
+ end
32
+
33
+ Jeweler::GemcutterTasks.new
34
+
35
+ FileList['tasks/**/*.rake'].each { |task| import task }
36
+ rescue LoadError
37
+ puts 'Jeweler (or a dependency) not available. Install it with: gem install jeweler'
38
+ end
39
+
40
+ task(:spec) {} # stub out the spec task for as long as we don't have any specs
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.2
@@ -0,0 +1,2 @@
1
+ require 'restful_route_version/railtie'
2
+
@@ -0,0 +1,15 @@
1
+ module RestfulRouteVersion
2
+ module DependencyExt
3
+ mattr_accessor :dynamically_defined_constants
4
+ self.dynamically_defined_constants = Set.new()
5
+
6
+ def remove_unloadable_constants!
7
+ autoloaded_constants.each { |const|
8
+ remove_constant const unless dynamically_defined_constants.include?(const)
9
+ }
10
+ autoloaded_constants.clear
11
+ ActiveSupport::Dependencies::Reference.clear!
12
+ explicitly_unloadable_constants.each { |const| remove_constant const }
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,26 @@
1
+ module RestfulRouteVersion
2
+
3
+ module ControllerExt
4
+ def restful_route_version
5
+ view_paths.each do |path|
6
+ append_view_path(InheritedViewResolver.new(path.to_s))
7
+ end
8
+ end
9
+ end
10
+
11
+ class InheritedViewResolver < ::ActionView::FileSystemResolver
12
+ def find_templates(name, prefix, partial, details)
13
+ klass = "#{prefix}_controller".camelize.constantize rescue nil
14
+
15
+ return [] if !klass || !(klass < ActionController::Base)
16
+
17
+ ancestor = klass.ancestors.second
18
+ ancestor_prefix = ancestor.name.gsub(/Controller$/, '').underscore
19
+
20
+ templates = super(name, ancestor_prefix, partial, details)
21
+ return templates if templates.present?
22
+ find_templates(name, ancestor_prefix, partial, details)
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,22 @@
1
+ require "rails"
2
+
3
+ require "restful_route_version/dependency_ext"
4
+ require "restful_route_version/version_mapper"
5
+ require "restful_route_version/inherited_view_resolver"
6
+
7
+ module RestfulRouteVersion
8
+ VERSION = '0.0.2'
9
+ class Railtie < Rails::Railtie
10
+
11
+ initializer "restful_route_version.configure_rails_initialization" do
12
+ ActionDispatch::Routing::Mapper.send(:include, RestfulRouteVersion::VersionMapper)
13
+ ActiveSupport::Dependencies.send(:include, RestfulRouteVersion::DependencyExt)
14
+ ActiveSupport::Dependencies.extend(RestfulRouteVersion::DependencyExt)
15
+ ActionController::Base.extend(ControllerExt)
16
+ end
17
+ end
18
+ end
19
+
20
+
21
+
22
+
@@ -0,0 +1,109 @@
1
+ module RestfulRouteVersion
2
+ module VersionMapper
3
+ attr_accessor :cached_namespace_blocks
4
+ def version_namespace(path, options = {}, &block)
5
+ #puts "Calling version_namespace"
6
+ path = path.to_s
7
+ options = { :path => path, :as => path, :module => path,
8
+ :shallow_path => path, :shallow_prefix => path }.merge!(options)
9
+
10
+ @cached_namespace_blocks ||= {}
11
+
12
+
13
+ scope(options) {
14
+ create_controller_class(@scope[:module].to_s.camelize,Module.new)
15
+ @cached_namespace_blocks[@scope[:path]] = block if options[:cache_route]
16
+ block.call
17
+ }
18
+ end
19
+
20
+ def resources(*resources, &block)
21
+ except_options = @scope[:options][:except]
22
+ return if skip_resource?(resources,except_options)
23
+ super(*resources, &block)
24
+ end
25
+
26
+ def resource(*resources, &block)
27
+ except_options = @scope[:options][:except]
28
+ return if skip_resource?(resources,except_options)
29
+ super(*resources, &block)
30
+ end
31
+
32
+ def skip_resource?(resources, except_options)
33
+ #puts "********** incoming #{resources.inspect} and except_options #{except_options.inspect} and path #{@scope[:path]} **********"
34
+ return false if(resources.length > 1 || except_options.blank?)
35
+ return true if except_options.include?(resources.first.to_s)
36
+ false
37
+ end
38
+
39
+ def inherit_routes(*entities)
40
+ #puts "Current path #{@scope[:path]} and old one #{entities.first}"
41
+ options = entities.extract_options!
42
+ new_options = merge_except_options(options)
43
+ #puts "New options are #{new_options.inspect}"
44
+ new_options[:old_namespace] = @scope[:options][:old_namespace] || entities.dup.shift
45
+
46
+
47
+ entities.each { |entity|
48
+ inherited_route_block = @cached_namespace_blocks[entity]
49
+ inherited_route_block && scope(new_options) do
50
+ inherited_route_block.call()
51
+ end
52
+ }
53
+ create_derived_controllers(new_options[:old_namespace], new_options)
54
+ end
55
+
56
+ def merge_except_options(options)
57
+ options[:except] ||= []
58
+ options[:namespace] = @scope[:path]
59
+ if old_exception_option = @scope[:options][:except]
60
+ options[:except] += old_exception_option
61
+ end
62
+ options
63
+ end
64
+
65
+ def create_derived_controllers(old_namespace, options = {})
66
+ old_namespace.gsub!(/^\/?/,'')
67
+ current_namespace = options[:namespace].gsub(/^\/?/,'')
68
+ Dir["#{Rails.root}/app/controllers/#{old_namespace}/*.rb"].each do |controller_file_name|
69
+ require_or_load(controller_file_name)
70
+ end
71
+
72
+ exclude_constants = options[:except].blank? ? [] : options[:except]
73
+
74
+ controllers_to_exclude = exclude_constants.map { |x| (old_namespace + "/#{x}Controller").camelize }
75
+ #puts "Old namespace is #{old_namespace}"
76
+ old_namespace.camelize.constantize.constants.each do |constant_name|
77
+ #puts "Incoming constant #{constant_name}"
78
+ full_constant_name = old_namespace.camelize + "::" + constant_name.to_s
79
+ new_controller_name = "#{current_namespace.camelize}::#{constant_name}"
80
+ #puts "Defining constant #{new_controller_name} with parent #{full_constant_name}"
81
+ if create_controller_dynamically?(controllers_to_exclude, full_constant_name, new_controller_name)
82
+ create_controller_class(new_controller_name,Class.new(full_constant_name.constantize))
83
+ end
84
+ end
85
+ end
86
+
87
+ def create_controller_dynamically?(controllers_to_exclude, old_controller_name, new_controller_name)
88
+ !controllers_to_exclude.include?(old_controller_name) &&
89
+ old_controller_name =~ /Controller$/ &&
90
+ !File.exists?("#{Rails.root}/app/controllers/#{new_controller_name.underscore}.rb")
91
+ end
92
+
93
+
94
+ def create_controller_class(full_constant_name, klass_constant)
95
+ #puts "Full constant_name is #{full_constant_name}"
96
+ names = full_constant_name.split('::')
97
+ ActiveSupport::Dependencies.dynamically_defined_constants << full_constant_name
98
+ names.shift if names.empty? || names.first.empty?
99
+ constant = Object
100
+ names.each do |name|
101
+ if constant.const_defined?(name)
102
+ constant = constant.const_get(name)
103
+ else
104
+ constant = constant.const_set(name, klass_constant)
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,99 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{restful_route_version}
8
+ s.version = "0.0.2"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Hemant Kumar"]
12
+ s.date = %q{2011-06-12}
13
+ s.description = %q{Versioning your routes in Rails3}
14
+ s.email = %q{gethemant@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.md"
18
+ ]
19
+ s.files = [
20
+ "Gemfile",
21
+ "Gemfile.lock",
22
+ "LICENSE",
23
+ "MIT-LICENSE",
24
+ "README.md",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "lib/restful_route_version.rb",
28
+ "lib/restful_route_version/dependency_ext.rb",
29
+ "lib/restful_route_version/inherited_view_resolver.rb",
30
+ "lib/restful_route_version/railtie.rb",
31
+ "lib/restful_route_version/version_mapper.rb",
32
+ "restful_route_version.gemspec",
33
+ "test/dependency_ext_test.rb",
34
+ "test/fixture_files/a.rb",
35
+ "test/fixture_files/b.rb",
36
+ "test/fixture_files/c.rb",
37
+ "test/rails_sandbox/app/controllers/api/v10/articles_controller.rb",
38
+ "test/rails_sandbox/app/controllers/api/v10/notes_controller.rb",
39
+ "test/rails_sandbox/app/controllers/api/v10/questions_controller.rb",
40
+ "test/rails_sandbox/app/controllers/api/v10/songs_controller.rb",
41
+ "test/rails_sandbox/app/controllers/api/v11/articles_controller.rb",
42
+ "test/rails_sandbox/app/controllers/api/v11/tags_controller.rb",
43
+ "test/rails_sandbox/app/views/api/v10/songs/_bar.erb",
44
+ "test/rails_sandbox/app/views/api/v10/songs/create.html.erb",
45
+ "test/rails_sandbox/app/views/api/v10/songs/foo.html.erb",
46
+ "test/rails_sandbox/app/views/api/v10/songs/index.html.erb",
47
+ "test/rails_sandbox/app/views/api/v10/songs/show.html.erb",
48
+ "test/rails_sandbox/app/views/api/v11/songs/_wow.html.erb",
49
+ "test/rails_sandbox/app/views/api/v11/songs/bar.html.erb",
50
+ "test/rails_sandbox/app/views/api/v11/songs/baz.html.erb",
51
+ "test/rails_sandbox/app/views/api/v11/songs/show.html.erb",
52
+ "test/test_helper.rb",
53
+ "test/version_mapper_test.rb"
54
+ ]
55
+ s.homepage = %q{http://github.com/gnufied/restful_route_version}
56
+ s.require_paths = ["lib"]
57
+ s.rubyforge_project = %q{restful_route_version}
58
+ s.rubygems_version = %q{1.6.2}
59
+ s.summary = %q{Versioning your routes in Rails3}
60
+ s.test_files = [
61
+ "test/dependency_ext_test.rb",
62
+ "test/fixture_files/a.rb",
63
+ "test/fixture_files/b.rb",
64
+ "test/fixture_files/c.rb",
65
+ "test/rails_sandbox/app/controllers/api/v10/articles_controller.rb",
66
+ "test/rails_sandbox/app/controllers/api/v10/notes_controller.rb",
67
+ "test/rails_sandbox/app/controllers/api/v10/questions_controller.rb",
68
+ "test/rails_sandbox/app/controllers/api/v10/songs_controller.rb",
69
+ "test/rails_sandbox/app/controllers/api/v11/articles_controller.rb",
70
+ "test/rails_sandbox/app/controllers/api/v11/tags_controller.rb",
71
+ "test/test_helper.rb",
72
+ "test/version_mapper_test.rb"
73
+ ]
74
+
75
+ if s.respond_to? :specification_version then
76
+ s.specification_version = 3
77
+
78
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
79
+ s.add_runtime_dependency(%q<rails>, ["= 3.0.7"])
80
+ s.add_runtime_dependency(%q<rake>, [">= 0"])
81
+ s.add_runtime_dependency(%q<activesupport>, ["~> 3.0.0"])
82
+ s.add_runtime_dependency(%q<actionpack>, ["~> 3.0.0"])
83
+ s.add_runtime_dependency(%q<railties>, ["~> 3.0.0"])
84
+ else
85
+ s.add_dependency(%q<rails>, ["= 3.0.7"])
86
+ s.add_dependency(%q<rake>, [">= 0"])
87
+ s.add_dependency(%q<activesupport>, ["~> 3.0.0"])
88
+ s.add_dependency(%q<actionpack>, ["~> 3.0.0"])
89
+ s.add_dependency(%q<railties>, ["~> 3.0.0"])
90
+ end
91
+ else
92
+ s.add_dependency(%q<rails>, ["= 3.0.7"])
93
+ s.add_dependency(%q<rake>, [">= 0"])
94
+ s.add_dependency(%q<activesupport>, ["~> 3.0.0"])
95
+ s.add_dependency(%q<actionpack>, ["~> 3.0.0"])
96
+ s.add_dependency(%q<railties>, ["~> 3.0.0"])
97
+ end
98
+ end
99
+
@@ -0,0 +1,50 @@
1
+ require_relative "test_helper"
2
+
3
+ class RestfulRouteVersionDependenciesTest < Test::Unit::TestCase
4
+ context "For RestfulRouteVersionDependencies" do
5
+ setup do
6
+ ActiveSupport::Dependencies.dynamically_defined_constants << "Foo"
7
+ ActiveSupport::Dependencies.dynamically_defined_constants << "Bar"
8
+ ActiveSupport::Dependencies.dynamically_defined_constants << "C"
9
+ end
10
+
11
+ should "only remove constants which were not dynamically defined" do
12
+ with_autoloading_fixtures do
13
+ Object.const_set(:Foo,Class.new)
14
+ Object.const_set(:Bar,Class.new)
15
+ Object.const_get(:A)
16
+ Object.const_get(:B)
17
+ Object.const_get(:C)
18
+ ActiveSupport::Dependencies.clear
19
+ assert !Object.const_defined?(:A)
20
+ assert !Object.const_defined?(:B)
21
+ assert Object.const_defined?(:Foo)
22
+ assert Object.const_defined?(:Bar)
23
+ assert Object.const_defined?(:C)
24
+ end
25
+ end
26
+ end
27
+
28
+ def with_loading(*from)
29
+ old_mechanism, ActiveSupport::Dependencies.mechanism = ActiveSupport::Dependencies.mechanism, :load
30
+ this_dir = File.dirname(__FILE__)
31
+ parent_dir = File.dirname(this_dir)
32
+ path_copy = $LOAD_PATH.dup
33
+ $LOAD_PATH.unshift(parent_dir) unless $LOAD_PATH.include?(parent_dir)
34
+ prior_autoload_paths = ActiveSupport::Dependencies.autoload_paths
35
+ ActiveSupport::Dependencies.autoload_paths = from.collect { |f| "#{this_dir}/#{f}" }
36
+ yield
37
+ ensure
38
+ $LOAD_PATH.replace(path_copy)
39
+ ActiveSupport::Dependencies.autoload_paths = prior_autoload_paths
40
+ ActiveSupport::Dependencies.mechanism = old_mechanism
41
+ ActiveSupport::Dependencies.explicitly_unloadable_constants = []
42
+ end
43
+
44
+ def with_autoloading_fixtures(&block)
45
+ with_loading 'fixture_files', &block
46
+ end
47
+
48
+ end
49
+
50
+
@@ -0,0 +1,2 @@
1
+ class A
2
+ end
@@ -0,0 +1,2 @@
1
+ class B
2
+ end
@@ -0,0 +1,2 @@
1
+ class C
2
+ end
@@ -0,0 +1,10 @@
1
+ module Api
2
+ module V10
3
+ class ArticlesController < ActionController::Base
4
+ restful_route_version
5
+ def index
6
+ render :text => "Hello world from v10 ArticlesController"
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,6 @@
1
+ class Api::V10::NotesController < ActionController::Base
2
+ restful_route_version
3
+ def index
4
+ render :text => "Hello from V10 notes controller, lolz"
5
+ end
6
+ end
@@ -0,0 +1,10 @@
1
+ module Api
2
+ module V10
3
+ class QuestionsController < ActionController::Base
4
+ restful_route_version
5
+ def index
6
+ render :text => "Hello world from v10 QuestionsController"
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,26 @@
1
+ module Api
2
+ module V10
3
+ class SongsController < ActionController::Base
4
+ restful_route_version
5
+ def index
6
+ end
7
+
8
+ def show
9
+
10
+ end
11
+
12
+ def create
13
+ end
14
+
15
+ def foo
16
+ end
17
+
18
+ def bar
19
+
20
+ end
21
+
22
+ def baz
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,9 @@
1
+ module Api
2
+ module V11
3
+ class ArticlesController < Api::V10::ArticlesController
4
+ def index
5
+ render :text => "Hello world from v11 ArticlesController"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Api
2
+ module V11
3
+ class TagsController < ActionController::Base
4
+ def index
5
+ render :text => "Hello world from v11 ArticlesController"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1 @@
1
+ Calling Songs#create from v10
@@ -0,0 +1 @@
1
+ Calling Foo from <%= render :partial => 'bar' -%>
@@ -0,0 +1 @@
1
+ Hello from v10 of Music#index
@@ -0,0 +1 @@
1
+ Calling Songs#show from v10
@@ -0,0 +1 @@
1
+ Dude this is <%= render :partial => 'bleh' -%>
@@ -0,0 +1 @@
1
+ Hello from <%= render :partial => 'wow' -%> dude
@@ -0,0 +1 @@
1
+ Calling Songs#show from v11
@@ -0,0 +1,60 @@
1
+ require "rubygems"
2
+ gem 'activesupport', '~> 3.0.7'
3
+ gem 'actionpack', '~> 3.0.7'
4
+ gem 'activerecord', '~> 3.0.7'
5
+ gem 'rails', '~> 3.0.7'
6
+
7
+ require "active_support"
8
+ require "active_support/dependencies"
9
+ require "active_support/core_ext/hash/slice"
10
+ require "action_controller"
11
+ require "action_view"
12
+ require "action_pack"
13
+
14
+ require "shoulda"
15
+
16
+ class MockLogger
17
+ attr_reader :logged
18
+
19
+ def initialize
20
+ @logged = []
21
+ end
22
+
23
+ def method_missing(method, *args)
24
+ @logged << args.first
25
+ end
26
+ end
27
+
28
+ class MockBacktraceCleaner < ActiveSupport::BacktraceCleaner
29
+ end
30
+
31
+ $:<< File.join(File.dirname(__FILE__), "..", "lib")
32
+ $:<< File.join(File.dirname(__FILE__), "rails_sandbox", "app", "controllers")
33
+
34
+ require "restful_route_version"
35
+ ActionDispatch::Routing::Mapper.send(:include, RestfulRouteVersion::VersionMapper)
36
+ ActiveSupport::Dependencies.send(:include, RestfulRouteVersion::DependencyExt)
37
+ ActiveSupport::Dependencies.extend(RestfulRouteVersion::DependencyExt)
38
+ ActionController::Base.extend(RestfulRouteVersion::ControllerExt)
39
+
40
+ module Rails
41
+ def self.root
42
+ File.expand_path(File.join(File.dirname(__FILE__), "rails_sandbox"))
43
+ end
44
+
45
+ def self.backtrace_cleaner
46
+ @@backtrace_cleaner ||= MockBacktraceCleaner.new()
47
+ end
48
+ def self.env
49
+ @_env ||= ActiveSupport::StringInquirer.new(ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "test")
50
+ end
51
+
52
+ def self.env_defaults
53
+ {}
54
+ end
55
+
56
+ def self.application
57
+ self
58
+ end
59
+ end
60
+
@@ -0,0 +1,201 @@
1
+ require_relative "test_helper"
2
+
3
+ class VersionMapperTest < Test::Unit::TestCase
4
+ context "Versioned routing extension" do
5
+ setup do
6
+ @route_set = ActionDispatch::Routing::RouteSet.new()
7
+ @mapper = ActionDispatch::Routing::Mapper.new(@route_set)
8
+ end
9
+
10
+ should "provide version_namespace routing method" do
11
+ assert @mapper.respond_to?(:version_namespace)
12
+ end
13
+
14
+ should "capture specified namespace when using version_namespace" do
15
+ route_block = lambda do
16
+ version_namespace("foo") do
17
+ resources :articles
18
+ end
19
+ end
20
+ @mapper.instance_exec(&route_block)
21
+ assert !ActiveSupport::Dependencies.dynamically_defined_constants.blank?
22
+ end
23
+
24
+ should "capture route block if cache_route is true when using version_namespace" do
25
+ route_block = lambda do
26
+ version_namespace("foo", :cache_route => true) do
27
+ resources :articles
28
+ end
29
+ end
30
+ @mapper.instance_exec(&route_block)
31
+ assert !@mapper.cached_namespace_blocks["/foo"].blank?
32
+ end
33
+
34
+ should "provide inherit_routes routing method" do
35
+ assert @mapper.respond_to?(:inherit_routes)
36
+ end
37
+ end
38
+
39
+ context "Restful route extension with inherit_routes" do
40
+ setup do
41
+ @route_set = ActionDispatch::Routing::RouteSet.new()
42
+ @mapper = ActionDispatch::Routing::Mapper.new(@route_set)
43
+
44
+ @route_block = lambda do
45
+ version_namespace :api do
46
+ version_namespace(:v10,:cache_route => true) do
47
+ resources :articles
48
+ resources :comments
49
+ resources :notes
50
+ end
51
+
52
+ version_namespace(:v11, :cache_route => true) do
53
+ inherit_routes("/api/v10", :except => %w(articles))
54
+ resources :articles
55
+ resources :tags
56
+ end
57
+
58
+ version_namespace(:v12) do
59
+ inherit_routes("/api/v11",:except => %w(notes))
60
+ resources :lessons
61
+ end
62
+ end #end of map.version_namespace(:api)
63
+ end #end of route_block
64
+
65
+ end #end of setup block
66
+
67
+ should "create derived routes when using inherit_routes" do
68
+ @mapper.instance_exec(&@route_block)
69
+ v12_tag_route = @route_set.named_routes.routes[:edit_api_v12_tag]
70
+ assert !v12_tag_route.blank?
71
+ assert_match /\/api\/v12\/tags\/\:id\/edit/, v12_tag_route.to_s
72
+ end
73
+
74
+ should "not create routes for except resources" do
75
+ @mapper.instance_exec(&@route_block)
76
+ article_route = @route_set.named_routes.routes[:new_api_v12_article]
77
+ assert !article_route.blank?
78
+
79
+ note_route = @route_set.named_routes.routes[:new_api_v12_note]
80
+ assert note_route.blank?
81
+ end
82
+ end
83
+
84
+ context "Restful route extension with inherit_routes and creating controllers dynamically" do
85
+ setup do
86
+ @route_set = ActionDispatch::Routing::RouteSet.new()
87
+ @mapper = ActionDispatch::Routing::Mapper.new(@route_set)
88
+
89
+ @route_block = lambda do
90
+ version_namespace :api do
91
+ version_namespace(:v10,:cache_route => true) do
92
+ resources :articles
93
+ resources :notes
94
+ end
95
+
96
+ version_namespace(:v11, :cache_route => true) do
97
+ inherit_routes("/api/v10", :except => %w(articles))
98
+ resources :tags
99
+ resources :articles
100
+ end
101
+
102
+ version_namespace(:v12) do
103
+ inherit_routes("/api/v11")
104
+ resources :lessons
105
+ end
106
+
107
+ end #end of map.version_namespace(:api)
108
+ end #end of route_block
109
+ end #end of setup block
110
+
111
+ should "automatically load classes which has to be loaded dynamically" do
112
+ @mapper.instance_exec(&@route_block)
113
+ assert defined?(Api::V11::NotesController)
114
+ t_superclass = Api::V11::NotesController.superclass.to_s
115
+ assert_equal "Api::V10::NotesController", t_superclass
116
+
117
+ assert defined?(Api::V12::NotesController)
118
+ assert_equal "Api::V11::NotesController", Api::V12::NotesController.superclass.to_s
119
+ end
120
+ end #end of context inherit_routes
121
+
122
+
123
+ context "Inherit controller with except" do
124
+ setup do
125
+ @route_set = ActionDispatch::Routing::RouteSet.new()
126
+ @mapper = ActionDispatch::Routing::Mapper.new(@route_set)
127
+
128
+ @route_block = lambda do
129
+ version_namespace :api do
130
+ version_namespace(:v10,:cache_route => true) do
131
+ resources :articles
132
+ resources :notes
133
+ end
134
+
135
+ version_namespace(:v11, :cache_route => true) do
136
+ inherit_routes("api/v10", :except => %w(articles))
137
+ resources :tags
138
+ resources :articles
139
+ end
140
+
141
+ version_namespace(:v12) do
142
+ inherit_routes("api/v11", :except => %w(tags))
143
+ resources :lessons
144
+ end
145
+
146
+ end #end of map.version_namespace(:api)
147
+ end #end of route_block
148
+ end #end of setup block
149
+
150
+ should "not create controllers in only specified namespace" do
151
+ @mapper.instance_exec(&@route_block)
152
+ ActiveSupport::Dependencies.remove_constant("Api::V12::TagsController")
153
+
154
+ assert defined?(Api::V11::ArticlesController)
155
+ assert defined?(Api::V12::ArticlesController)
156
+ assert (Api::V12::ArticlesController < Api::V11::ArticlesController)
157
+ assert (Api::V12::NotesController < Api::V11::NotesController)
158
+ assert (Api::V11::NotesController < Api::V10::NotesController)
159
+ assert !defined?(Api::V12::TagsController)
160
+ end
161
+ end
162
+
163
+ context "Inherit controller with except for non-existant" do
164
+ setup do
165
+ ActiveSupport::Dependencies.remove_constant("Api::V11::QuestionsController")
166
+ ActiveSupport::Dependencies.remove_constant("Api::V12::QuestionsController")
167
+ @route_set = ActionDispatch::Routing::RouteSet.new()
168
+ @mapper = ActionDispatch::Routing::Mapper.new(@route_set)
169
+
170
+ @route_block = lambda do
171
+ version_namespace :api do
172
+ version_namespace(:v10,:cache_route => true) do
173
+ resources :articles
174
+ resources :notes
175
+ resources :questions
176
+ end
177
+
178
+ version_namespace(:v11, :cache_route => true) do
179
+ inherit_routes("api/v10", :except => %w(articles questions))
180
+ resources :tags
181
+ resources :articles
182
+ end
183
+
184
+ version_namespace(:v12) do
185
+ inherit_routes("api/v11")
186
+ resources :lessons
187
+ end
188
+ end #end of map.version_namespace(:api)
189
+ end #end of route_block
190
+
191
+ end #end of setup block
192
+
193
+ should "not create controllers in only specified namespace" do
194
+ @mapper.instance_exec(&@route_block)
195
+ assert defined?(Api::V10::QuestionsController)
196
+ assert !defined?(Api::V11::QuestionsController)
197
+ assert !defined?(Api::V12::QuestionsController)
198
+ end
199
+ end
200
+
201
+ end
metadata ADDED
@@ -0,0 +1,158 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: restful_route_version
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.2
6
+ platform: ruby
7
+ authors:
8
+ - Hemant Kumar
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-06-12 00:00:00 +05:30
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: rails
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - "="
22
+ - !ruby/object:Gem::Version
23
+ version: 3.0.7
24
+ type: :runtime
25
+ prerelease: false
26
+ version_requirements: *id001
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: &id002 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: "0"
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: *id002
38
+ - !ruby/object:Gem::Dependency
39
+ name: activesupport
40
+ requirement: &id003 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 3.0.0
46
+ type: :runtime
47
+ prerelease: false
48
+ version_requirements: *id003
49
+ - !ruby/object:Gem::Dependency
50
+ name: actionpack
51
+ requirement: &id004 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ~>
55
+ - !ruby/object:Gem::Version
56
+ version: 3.0.0
57
+ type: :runtime
58
+ prerelease: false
59
+ version_requirements: *id004
60
+ - !ruby/object:Gem::Dependency
61
+ name: railties
62
+ requirement: &id005 !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ~>
66
+ - !ruby/object:Gem::Version
67
+ version: 3.0.0
68
+ type: :runtime
69
+ prerelease: false
70
+ version_requirements: *id005
71
+ description: Versioning your routes in Rails3
72
+ email: gethemant@gmail.com
73
+ executables: []
74
+
75
+ extensions: []
76
+
77
+ extra_rdoc_files:
78
+ - LICENSE
79
+ - README.md
80
+ files:
81
+ - Gemfile
82
+ - Gemfile.lock
83
+ - LICENSE
84
+ - MIT-LICENSE
85
+ - README.md
86
+ - Rakefile
87
+ - VERSION
88
+ - lib/restful_route_version.rb
89
+ - lib/restful_route_version/dependency_ext.rb
90
+ - lib/restful_route_version/inherited_view_resolver.rb
91
+ - lib/restful_route_version/railtie.rb
92
+ - lib/restful_route_version/version_mapper.rb
93
+ - restful_route_version.gemspec
94
+ - test/dependency_ext_test.rb
95
+ - test/fixture_files/a.rb
96
+ - test/fixture_files/b.rb
97
+ - test/fixture_files/c.rb
98
+ - test/rails_sandbox/app/controllers/api/v10/articles_controller.rb
99
+ - test/rails_sandbox/app/controllers/api/v10/notes_controller.rb
100
+ - test/rails_sandbox/app/controllers/api/v10/questions_controller.rb
101
+ - test/rails_sandbox/app/controllers/api/v10/songs_controller.rb
102
+ - test/rails_sandbox/app/controllers/api/v11/articles_controller.rb
103
+ - test/rails_sandbox/app/controllers/api/v11/tags_controller.rb
104
+ - test/rails_sandbox/app/views/api/v10/songs/_bar.erb
105
+ - test/rails_sandbox/app/views/api/v10/songs/create.html.erb
106
+ - test/rails_sandbox/app/views/api/v10/songs/foo.html.erb
107
+ - test/rails_sandbox/app/views/api/v10/songs/index.html.erb
108
+ - test/rails_sandbox/app/views/api/v10/songs/show.html.erb
109
+ - test/rails_sandbox/app/views/api/v11/songs/_wow.html.erb
110
+ - test/rails_sandbox/app/views/api/v11/songs/bar.html.erb
111
+ - test/rails_sandbox/app/views/api/v11/songs/baz.html.erb
112
+ - test/rails_sandbox/app/views/api/v11/songs/show.html.erb
113
+ - test/test_helper.rb
114
+ - test/version_mapper_test.rb
115
+ has_rdoc: true
116
+ homepage: http://github.com/gnufied/restful_route_version
117
+ licenses: []
118
+
119
+ post_install_message:
120
+ rdoc_options: []
121
+
122
+ require_paths:
123
+ - lib
124
+ required_ruby_version: !ruby/object:Gem::Requirement
125
+ none: false
126
+ requirements:
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ hash: -2262431187530772954
130
+ segments:
131
+ - 0
132
+ version: "0"
133
+ required_rubygems_version: !ruby/object:Gem::Requirement
134
+ none: false
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: "0"
139
+ requirements: []
140
+
141
+ rubyforge_project: restful_route_version
142
+ rubygems_version: 1.6.2
143
+ signing_key:
144
+ specification_version: 3
145
+ summary: Versioning your routes in Rails3
146
+ test_files:
147
+ - test/dependency_ext_test.rb
148
+ - test/fixture_files/a.rb
149
+ - test/fixture_files/b.rb
150
+ - test/fixture_files/c.rb
151
+ - test/rails_sandbox/app/controllers/api/v10/articles_controller.rb
152
+ - test/rails_sandbox/app/controllers/api/v10/notes_controller.rb
153
+ - test/rails_sandbox/app/controllers/api/v10/questions_controller.rb
154
+ - test/rails_sandbox/app/controllers/api/v10/songs_controller.rb
155
+ - test/rails_sandbox/app/controllers/api/v11/articles_controller.rb
156
+ - test/rails_sandbox/app/controllers/api/v11/tags_controller.rb
157
+ - test/test_helper.rb
158
+ - test/version_mapper_test.rb