svenfuchs-routing-filter 0.0.1

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.
@@ -0,0 +1 @@
1
+ vendor
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Sven Fuchs
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,123 @@
1
+ ## Routing Filter
2
+
3
+ This plugin is a wild hack that wraps around the complex beast that the Rails
4
+ routing system is to allow for unseen flexibility and power in Rails URL
5
+ recognition and generation.
6
+
7
+ As powerful and awesome the Rails' routes are, when you need to design your
8
+ URLs in a manner that only slightly leaves the paved cowpaths of Rails
9
+ conventions, you're usually unable to use all the goodness of helpers and
10
+ convenience that Rails ships with.
11
+
12
+ ## Usage
13
+
14
+ This plugin comes with a locale routing filter that demonstrates the
15
+ implementation of a custom filter.
16
+
17
+ The following would be a sceleton of an empty filter:
18
+
19
+ module RoutingFilter
20
+ class Awesomeness < Base
21
+ def around_recognize(route, path, env)
22
+ # Alter the path here before it gets recognized.
23
+ # Make sure to yield (calls the next around filter if present and
24
+ # eventually `recognize_path` on the routeset):
25
+ returning yield do |params|
26
+ # You can additionally modify the params here before they get passed
27
+ # to the controller.
28
+ end
29
+ end
30
+
31
+ def around_generate(controller, *args, &block)
32
+ # Alter arguments here before they are passed to `url_for`.
33
+ # Make sure to yield (calls the next around filter if present and
34
+ # eventually `url_for` on the controller):
35
+ returning yield do |result|
36
+ # You can change the generated url_or_path here. Make sure to use
37
+ # one of the "in-place" modifying String methods though (like sub!
38
+ # and friends).
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ You then have to specify the filter explicitely in your routes.rb:
45
+
46
+ ActionController::Routing::Routes.draw do |map|
47
+ map.filter 'awesomeness'
48
+ end
49
+
50
+ (I am not sure if it makes sense to provide more technical information than
51
+ this because the usage of this plugin definitely requires some advanced
52
+ knowledge about Rails internals and especially its routing system. So, I
53
+ figure, anyone who could use this should also be able to read the code and
54
+ figure out what it's doing much better then from any lengthy documentation.
55
+
56
+ If I'm mistaken on this please drop me an email with your suggestions.)
57
+
58
+
59
+ ## Rationale: Two example usecases
60
+
61
+ An early usecase from which this originated was the need to define a locale
62
+ at the beginning of an URL in a way so that
63
+
64
+ * the locale can be omitted when it is the default locale
65
+ * all the url\_helpers that are generated by named routes continue to work in
66
+ a concise manner (i.e. without specifying all parameters again and again)
67
+ * ideally also plays nicely with default route helpers in tests/specs
68
+
69
+ You can read about this struggle and two possible, yet unsatisfying solutions
70
+ [here](http://www.artweb-design.de/2007/5/13/concise-localized-rails-url-helpers-solved-twice).
71
+ The conclusion so far is that Rails itself does not provide the tools to solve
72
+ this problem in a clean and dry way.
73
+
74
+ Another usecase that eventually spawned the manifestation of this plugin was
75
+ the need to map an arbitrary count of path segments to a certain model
76
+ instance. In an application that I've been working on recently I needed to
77
+ map URL paths to a nested tree of models like so:
78
+
79
+ root
80
+ + docs
81
+ + api
82
+ + wiki
83
+
84
+ E.g. the docs section should map to the path `/docs`, the api section to
85
+ the path `/docs/api` and so on. Furthermore, after these paths there need to be
86
+ more things to be specified. E.g. the wiki needs to define a whole Rails
87
+ resource with URLs like `/docs/wiki/pages/1/edit`.
88
+
89
+ The only way to solve this problem with Rails' routing toolkit is to map
90
+ a big, bold `/*everything` catch-all ("globbing") route and process the whole
91
+ path in a custom dispatcher.
92
+
93
+ This, of course, is a really unsatisfying solution because one has to
94
+ reimplement everything that Rails routes are here to help with: regarding both
95
+ URL recognition (like parameter mappings, resources, ...) and generation
96
+ (url\_helpers).
97
+
98
+ ## Solution
99
+
100
+ This plugin offers a solution that takes exactly the opposite route.
101
+
102
+ Instead of trying to change things *between* the URL recognition and
103
+ generation stages to achieve the desired result it *wraps around* the whole
104
+ routing system and allows to pre- and post-filter both what goes into it
105
+ (URL recognition) and what comes out of it (URL generation).
106
+
107
+ This way we can leave *everything* else completely untouched.
108
+
109
+ * We can tinker with the URLs that we receive from the server and feed URLs to
110
+ Rails that perfectly match the best breed of Rails' conventions.
111
+ * Inside of the application we can use all the nice helper goodness and
112
+ conveniences that rely on these conventions being followed.
113
+ * Finally we can accept URLs that have been generated by the url\_helpers and,
114
+ again, mutate them in the way that matches our requirements.
115
+
116
+ So, even though the plugin itself is a blatant monkey-patch to one of the
117
+ most complex area of Rails internals, this solution seems to be effectively
118
+ less intrusive and pricey than others are.
119
+
120
+ ## Etc
121
+
122
+ Authors: [Sven Fuchs](http://www.artweb-design.de) <svenfuchs at artweb-design dot de>
123
+ License: MIT
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.2
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'routing_filter'
@@ -0,0 +1,94 @@
1
+ module RoutingFilter
2
+ mattr_accessor :active
3
+ @@active = true
4
+
5
+ class Chain < Array
6
+ def << (filter)
7
+ filter.chain = self
8
+ super
9
+ end
10
+
11
+ def run(method, *args, &final)
12
+ RoutingFilter.active && !first.nil? ? first.run(method, *args, &final) : final.call
13
+ end
14
+
15
+ def run_reverse(method, *args, &final)
16
+ RoutingFilter.active && !last.nil? ? last.run_reverse(method, *args, &final) : final.call
17
+ end
18
+
19
+ def predecessor(filter)
20
+ ix = index(filter)
21
+ ix > 0 ? self[ix - 1] : nil
22
+ end
23
+
24
+ def successor(filter)
25
+ ix = index(filter)
26
+ ix < length - 1 ? self[ix + 1] : nil
27
+ end
28
+ end
29
+ end
30
+
31
+ # allows to install a filter to the route set by calling: map.filter 'locale'
32
+ ActionController::Routing::RouteSet::Mapper.class_eval do
33
+ def filter(name, options = {})
34
+ require options.delete(:file) || "routing_filter/#{name}"
35
+ klass = RoutingFilter.const_get(name.to_s.camelize)
36
+ @set.filters << klass.new(options)
37
+ end
38
+ end
39
+
40
+ # same here for the optimized url generation in named routes
41
+ ActionController::Routing::RouteSet::NamedRouteCollection.class_eval do
42
+ # gosh. monkey engineering optimization code
43
+ def generate_optimisation_block_with_filtering(*args)
44
+ code = generate_optimisation_block_without_filtering(*args)
45
+ if match = code.match(%r(^return (.*) if (.*)))
46
+ # returned string must not contain newlines, or we'll spill out of inline code comments in
47
+ # ActionController::Routing::RouteSet::NamedRouteCollection#define_url_helper
48
+ "returning(#{match[1]}) { |result|" +
49
+ " ActionController::Routing::Routes.filters.run_reverse(:around_generate, *args, &lambda{ result }) " +
50
+ "} if #{match[2]}"
51
+ end
52
+ end
53
+ alias_method_chain :generate_optimisation_block, :filtering
54
+ end
55
+
56
+ ActionController::Routing::RouteSet.class_eval do
57
+ def clear_with_filtering!
58
+ @filters.clear if @filters
59
+ clear_without_filtering!
60
+ end
61
+ alias_method_chain :clear!, :filtering
62
+
63
+ attr_writer :filters
64
+
65
+ def filters
66
+ @filters ||= RoutingFilter::Chain.new
67
+ end
68
+
69
+ def recognize_path_with_filtering(path, env = {})
70
+ path = ::URI.unescape(path.dup) # string is frozen due to memoize
71
+ filters.run(:around_recognize, path, env, &lambda{ recognize_path_without_filtering(path, env) })
72
+ end
73
+ alias_method_chain :recognize_path, :filtering
74
+
75
+ def generate_with_filtering(*args)
76
+ filters.run_reverse(:around_generate, args.first, &lambda{ generate_without_filtering(*args) })
77
+ end
78
+ alias_method_chain :generate, :filtering
79
+
80
+ # add some useful information to the request environment
81
+ # right, this is from jamis buck's excellent article about routes internals
82
+ # http://weblog.jamisbuck.org/2006/10/26/monkey-patching-rails-extending-routes-2
83
+ # TODO move this ... where?
84
+ alias_method :extract_request_environment_without_host, :extract_request_environment unless method_defined? :extract_request_environment_without_host
85
+ def extract_request_environment(request)
86
+ returning extract_request_environment_without_host(request) do |env|
87
+ env.merge! :host => request.host,
88
+ :port => request.port,
89
+ :host_with_port => request.host_with_port,
90
+ :domain => request.domain,
91
+ :subdomain => request.subdomains.first
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,31 @@
1
+ module RoutingFilter
2
+ class Base
3
+ class_inheritable_accessor :active
4
+ self.active = true
5
+
6
+ attr_accessor :chain, :options
7
+
8
+ def initialize(options = {})
9
+ @options = options
10
+ options.each { |name, value| instance_variable_set :"@#{name}", value }
11
+ end
12
+
13
+ def run(method, *args, &block)
14
+ _next = successor ? lambda { successor.run(method, *args, &block) } : block
15
+ active ? send(method, *args, &_next) : _next.call(*args)
16
+ end
17
+
18
+ def run_reverse(method, *args, &block)
19
+ _prev = predecessor ? lambda { predecessor.run(method, *args, &block) } : block
20
+ active ? send(method, *args, &_prev) : _prev.call(*args)
21
+ end
22
+
23
+ def predecessor
24
+ @chain.predecessor(self)
25
+ end
26
+
27
+ def successor
28
+ @chain.successor(self)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,57 @@
1
+ require 'routing_filter/base'
2
+
3
+ module RoutingFilter
4
+ class ForceExtension < Base
5
+ attr_reader :extension, :exclude
6
+
7
+ def initialize(*args)
8
+ super
9
+ @extension ||= 'html'
10
+ @exclude = %r(^(http.?://[^/]+)?\/?$) if @exclude.nil?
11
+ end
12
+
13
+ def around_recognize(path, env, &block)
14
+ extract_extension!(path) unless excluded?(path)
15
+ yield(path, env)
16
+ end
17
+
18
+ def around_generate(*args, &block)
19
+ returning yield do |result|
20
+ url = result.is_a?(Array) ? result.first : result
21
+ append_extension!(url) if append_extension?(url)
22
+ end
23
+ end
24
+
25
+ protected
26
+
27
+ def extract_extension!(path)
28
+ path.sub! /\.#{extension}$/, ''
29
+ $1
30
+ end
31
+
32
+ def append_extension?(url)
33
+ !(url.blank? || excluded?(url) || mime_extension?(url))
34
+ end
35
+
36
+ def excluded?(url)
37
+ case exclude
38
+ when Regexp
39
+ url =~ exclude
40
+ when Proc
41
+ exclude.call(url)
42
+ end
43
+ end
44
+
45
+ def mime_extension?(url)
46
+ url =~ /\.#{Mime::EXTENSION_LOOKUP.keys.join('|')}(\?|$)/
47
+ end
48
+
49
+ def append_extension!(url)
50
+ url.replace url.sub(/(\?|$)/, ".#{extension}\\1")
51
+ end
52
+
53
+ def append_page!(url, page)
54
+ url.replace "#{url}/pages/#{page}"
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,70 @@
1
+ require 'i18n'
2
+ require 'routing_filter/base'
3
+
4
+ module RoutingFilter
5
+ class Locale < Base
6
+ @@include_default_locale = true
7
+ cattr_writer :include_default_locale
8
+
9
+ class << self
10
+ def include_default_locale?
11
+ @@include_default_locale
12
+ end
13
+
14
+ def locales
15
+ @@locales ||= I18n.available_locales.map(&:to_sym)
16
+ end
17
+
18
+ def locales=(locales)
19
+ @@locales = locales.map(&:to_sym)
20
+ end
21
+
22
+ def locales_pattern
23
+ @@locales_pattern ||= %r(^/(#{self.locales.map { |l| Regexp.escape(l.to_s) }.join('|')})(?=/|$))
24
+ end
25
+ end
26
+
27
+ def around_recognize(path, env, &block)
28
+ locale = extract_locale!(path) # remove the locale from the beginning of the path
29
+ returning yield do |params| # invoke the given block (calls more filters and finally routing)
30
+ params[:locale] = locale if locale # set recognized locale to the resulting params hash
31
+ end
32
+ end
33
+
34
+ def around_generate(*args, &block)
35
+ locale = args.extract_options!.delete(:locale) # extract the passed :locale option
36
+ locale = I18n.locale if locale.nil? # default to I18n.locale when locale is nil (could also be false)
37
+ locale = nil unless valid_locale?(locale) # reset to no locale when locale is not valid
38
+
39
+ returning yield do |result|
40
+ if locale && prepend_locale?(locale)
41
+ url = result.is_a?(Array) ? result.first : result
42
+ prepend_locale!(url, locale)
43
+ end
44
+ end
45
+ end
46
+
47
+ protected
48
+
49
+ def extract_locale!(path)
50
+ path.sub! self.class.locales_pattern, ''
51
+ $1
52
+ end
53
+
54
+ def prepend_locale?(locale)
55
+ self.class.include_default_locale? || !default_locale?(locale)
56
+ end
57
+
58
+ def valid_locale?(locale)
59
+ locale && self.class.locales.include?(locale.to_sym)
60
+ end
61
+
62
+ def default_locale?(locale)
63
+ locale && locale.to_sym == I18n.default_locale.to_sym
64
+ end
65
+
66
+ def prepend_locale!(url, locale)
67
+ url.sub!(%r(^(http.?://[^/]*)?(.*))) { "#{$1}/#{locale}#{$2}" }
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,33 @@
1
+ require 'routing_filter/base'
2
+
3
+ module RoutingFilter
4
+ class Pagination < Base
5
+ def around_recognize(path, env, &block)
6
+ page = extract_page!(path)
7
+ returning yield(path, env) do |params|
8
+ params[:page] = page.to_i if page
9
+ end
10
+ end
11
+
12
+ def around_generate(*args, &block)
13
+ page = args.extract_options!.delete(:page)
14
+ returning yield do |result|
15
+ if page && page != 1
16
+ url = result.is_a?(Array) ? result.first : result
17
+ append_page!(url, page)
18
+ end
19
+ end
20
+ end
21
+
22
+ protected
23
+
24
+ def extract_page!(path)
25
+ path.sub! %r(/pages/([\d]+)/?$), ''
26
+ $1
27
+ end
28
+
29
+ def append_page!(url, page)
30
+ url.sub!(/($|\?)/) { "/pages/#{page}#{$1}" }
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,65 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ describe 'RoutingFilter::ForceExtension' do
4
+ include RoutingFilterHelpers
5
+
6
+ before :each do
7
+ setup_environment(:force_extension)
8
+ end
9
+
10
+ describe 'url recognition' do
11
+ it 'recognizes the path /sections/1.html' do
12
+ should_recognize_path '/sections/1.html', @section_params
13
+ end
14
+
15
+ it 'recognizes the path /sections/1/articles/1.html' do
16
+ should_recognize_path '/sections/1/articles/1.html', @article_params
17
+ end
18
+
19
+ it 'does not recognize the path /sections/1/articles/1.foobar' do
20
+ lambda { @set.recognize_path('/sections/1/articles/1.foobar', {}) }.should raise_error(ActionController::RoutingError)
21
+ end
22
+ end
23
+
24
+ describe 'url generation' do
25
+ it 'appends the .html extension to generated paths (section_path)' do
26
+ section_path(:id => 1).should == '/sections/1.html'
27
+ end
28
+
29
+ it 'appends the .html extension to generated paths (section_article_path)' do
30
+ section_article_path(:section_id => 1, :id => 1).should == '/sections/1/articles/1.html'
31
+ end
32
+
33
+ it 'appends the .html extension to generated paths (admin_articles_path)' do
34
+ admin_articles_path.should == '/admin/articles.html'
35
+ end
36
+
37
+ it 'does not replace or add on an existing extension' do
38
+ section_path(:id => 1, :format => 'xml').should == '/sections/1.xml'
39
+ end
40
+
41
+ it 'works with url query params' do
42
+ section_path(:id => 1, :foo => 'bar').should == '/sections/1.html?foo=bar'
43
+ end
44
+
45
+ it 'excludes / by default' do
46
+ home_path.should == '/'
47
+ end
48
+
49
+ it 'excludes http://test.host/ by default' do
50
+ home_url.should == 'http://test.host/'
51
+ end
52
+
53
+ it 'excludes with custom regexp' do
54
+ setup_environment { |map| map.filter :force_extension, :exclude => %r(^/(admin|$)) }
55
+ home_path.should == '/'
56
+ admin_articles_path.should == '/admin/articles'
57
+ section_path(:id => 1).should == '/sections/1.html'
58
+ end
59
+
60
+ it 'does not exclude / when :exclude => false was passed' do
61
+ setup_environment { |map| map.filter :force_extension, :exclude => false }
62
+ home_path.should == '/.html'
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,367 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ describe 'RoutingFilter', 'url generation' do
4
+ include RoutingFilterHelpers
5
+
6
+ before :each do
7
+ setup_environment :locale, :pagination
8
+
9
+ @site = Site.new
10
+ @section = Section.new
11
+ @article = Article.new
12
+ end
13
+
14
+ describe "named route url_helpers" do
15
+ describe "a not nested resource" do
16
+ it 'does not change the section_path when given page option equals 1' do
17
+ section_path(:id => 1, :page => 1).should == '/en/sections/1'
18
+ end
19
+
20
+ it 'appends the pages segments to section_path when given page option does not equal 1' do
21
+ section_path(:id => 1, :page => 2).should == '/en/sections/1/pages/2'
22
+ end
23
+
24
+ it 'prepends the current locale to section_path' do
25
+ I18n.locale = :de
26
+ section_path(:id => 1).should == '/de/sections/1'
27
+ end
28
+
29
+ it 'prepends a given locale param to section_path' do
30
+ I18n.locale = :de
31
+ section_path(:id => 1, :locale => :fi).should == '/fi/sections/1'
32
+ end
33
+
34
+ it 'does not prepend a locale to section_path if given locale is false' do
35
+ section_path(:id => 1, :locale => false).should == '/sections/1'
36
+ end
37
+
38
+ it 'works on section_path with both a locale and page option' do
39
+ section_path(:id => 1, :locale => :fi, :page => 2).should == '/fi/sections/1/pages/2'
40
+ end
41
+
42
+ it 'should not prepend an invalid locale to section_path' do
43
+ section_path(:id => 1, :locale => :aa).should == '/sections/1'
44
+ end
45
+
46
+ it 'should prepend a longer locale to section_path' do
47
+ section_path(:id => 1, :locale => 'en-US').should == '/en-US/sections/1'
48
+ end
49
+
50
+ it 'should not prepend the default locale when configured not to' do
51
+ RoutingFilter::Locale.include_default_locale = false
52
+ section_path(:id => 1, :locale => :en).should == '/sections/1'
53
+ end
54
+ end
55
+
56
+ describe "a nested resource" do
57
+ it 'does not change the section_article_path when given page option equals 1' do
58
+ section_article_path(:section_id => 1, :id => 1, :page => 1).should == '/en/sections/1/articles/1'
59
+ end
60
+
61
+ it 'appends the pages segments to section_article_path when given page option does not equal 1' do
62
+ section_article_path(:section_id => 1, :id => 1, :page => 2).should == '/en/sections/1/articles/1/pages/2'
63
+ end
64
+
65
+ it 'prepends the current locale to section_article_path' do
66
+ I18n.locale = :de
67
+ section_article_path(:section_id => 1, :id => 1).should == '/de/sections/1/articles/1'
68
+ end
69
+
70
+ it 'prepends a given locale param to section_article_path' do
71
+ I18n.locale = :de
72
+ section_article_path(:section_id => 1, :id => 1, :locale => :fi).should == '/fi/sections/1/articles/1'
73
+ end
74
+
75
+ it 'does not prepend a locale to section_article_path if given locale is false' do
76
+ section_article_path(:section_id => 1, :id => 1, :locale => false).should == '/sections/1/articles/1'
77
+ end
78
+
79
+ it 'works on section_article_path with both a locale and page option' do
80
+ section_article_path(:section_id => 1, :id => 1, :locale => :fi, :page => 2).should == '/fi/sections/1/articles/1/pages/2'
81
+ end
82
+
83
+ it 'should not prepend an invalid locale to section_article_path' do
84
+ section_article_path(:section_id => 1, :id => 1, :locale => :aa).should == '/sections/1/articles/1'
85
+ end
86
+
87
+ it 'should prepend a longer locale to section_article_path' do
88
+ section_article_path(:section_id => 1, :id => 1, :locale => 'en-US').should == '/en-US/sections/1/articles/1'
89
+ end
90
+
91
+ it 'should not prepend the default locale when configured not to' do
92
+ RoutingFilter::Locale.include_default_locale = false
93
+ section_article_path(:section_id => 1, :id => 1, :locale => :en).should == '/sections/1/articles/1'
94
+ end
95
+ end
96
+ end
97
+
98
+ describe 'when used with named route url_helper with "optimized" generation blocks' do
99
+ describe "a not nested resource" do
100
+ it 'does not change the section_path when given page option equals 1' do
101
+ section_path(1, :page => 1).should == '/en/sections/1'
102
+ end
103
+
104
+ it 'appends the pages segments to section_path when given page option does not equal 1' do
105
+ section_path(1, :page => 2).should == '/en/sections/1/pages/2'
106
+ end
107
+
108
+ it 'prepends the current locale to section_path' do
109
+ I18n.locale = :de
110
+ section_path(1).should == '/de/sections/1'
111
+ end
112
+
113
+ it 'prepends a given locale param to section_path' do
114
+ I18n.locale = :de
115
+ section_path(1, :locale => :fi).should == '/fi/sections/1'
116
+ end
117
+
118
+ it 'does not prepend a locale to section_path if given locale is false' do
119
+ section_path(1, :locale => false).should == '/sections/1'
120
+ end
121
+
122
+ it 'works for section_path with both a locale and page option' do
123
+ section_path(1, :locale => :fi, :page => 2).should == '/fi/sections/1/pages/2'
124
+ end
125
+
126
+ it 'should not prepend an invalid locale to section_path' do
127
+ section_path(1, :locale => :aa).should == '/sections/1'
128
+ end
129
+
130
+ it 'should prepend a longer locale to section_path' do
131
+ section_path(1, :locale => 'en-US').should == '/en-US/sections/1'
132
+ end
133
+
134
+ it 'should not prepend the default locale when configured not to' do
135
+ RoutingFilter::Locale.include_default_locale = false
136
+ section_path(1, :locale => :en).should == '/sections/1'
137
+ end
138
+ end
139
+
140
+ describe "a nested resource" do
141
+ it 'does not change the section_article_path when given page option equals 1' do
142
+ section_article_path(1, 1, :page => 1).should == '/en/sections/1/articles/1'
143
+ end
144
+
145
+ it 'appends the pages segments to section_article_path when given page option does not equal 1' do
146
+ section_article_path(1, 1, :page => 2).should == '/en/sections/1/articles/1/pages/2'
147
+ end
148
+
149
+ it 'prepends the current locale to section_article_path' do
150
+ I18n.locale = :de
151
+ section_article_path(1, 1).should == '/de/sections/1/articles/1'
152
+ end
153
+
154
+ it 'prepends a given locale param to section_article_path' do
155
+ I18n.locale = :de
156
+ section_article_path(1, 1, :locale => :fi).should == '/fi/sections/1/articles/1'
157
+ end
158
+
159
+ it 'does not prepend a locale to section_article_path if given locale is false' do
160
+ section_article_path(1, 1, :locale => false).should == '/sections/1/articles/1'
161
+ end
162
+
163
+ it 'works for section_article_path with both a locale and page option' do
164
+ section_article_path(1, 1, :locale => :fi, :page => 2).should == '/fi/sections/1/articles/1/pages/2'
165
+ end
166
+
167
+ it 'should not prepend an invalid locale to section_article_path' do
168
+ section_article_path(1, 1, :locale => :aa).should == '/sections/1/articles/1'
169
+ end
170
+
171
+ it 'should prepend a longer locale to section_article_path' do
172
+ section_article_path(1, 1, :locale => 'en-US').should == '/en-US/sections/1/articles/1'
173
+ end
174
+
175
+ it 'should not prepend the default locale when configured not to' do
176
+ RoutingFilter::Locale.include_default_locale = false
177
+ section_article_path(1, 1, :locale => :en).should == '/sections/1/articles/1'
178
+ end
179
+ end
180
+ end
181
+
182
+ describe 'when used with a polymorphic_path' do
183
+ describe "a not nested resource" do
184
+ it 'does not change the section_path when given page option equals 1' do
185
+ section_path(@section, :page => 1).should == '/en/sections/1'
186
+ end
187
+
188
+ it 'appends the pages segments to section_path when given page option does not equal 1' do
189
+ section_path(@section, :page => 2).should == '/en/sections/1/pages/2'
190
+ end
191
+
192
+ it 'prepends the current locale to section_path' do
193
+ I18n.locale = :de
194
+ section_path(@section).should == '/de/sections/1'
195
+ end
196
+
197
+ it 'prepends a given locale param to section_path' do
198
+ I18n.locale = :de
199
+ section_path(@section, :locale => :fi).should == '/fi/sections/1'
200
+ end
201
+
202
+ it 'does not prepend a locale to section_path if given locale is false' do
203
+ section_path(@section, :locale => false).should == '/sections/1'
204
+ end
205
+
206
+ it 'works for section_path with both a locale and page option' do
207
+ section_path(@section, :locale => :fi, :page => 2).should == '/fi/sections/1/pages/2'
208
+ end
209
+
210
+ it 'should not prepend an invalid locale to section_path' do
211
+ section_path(@section, :locale => :aa).should == '/sections/1'
212
+ end
213
+
214
+ it 'should prepend a longer locale to section_path' do
215
+ section_path(@section, :locale => 'en-US').should == '/en-US/sections/1'
216
+ end
217
+
218
+ it 'should not prepend the default locale when configured not to' do
219
+ RoutingFilter::Locale.include_default_locale = false
220
+ section_path(@section, :locale => :en).should == '/sections/1'
221
+ end
222
+ end
223
+
224
+ describe "a nested resource" do
225
+ it 'does not change the section_article_path when given page option equals 1' do
226
+ section_article_path(@section, @article, :page => 1).should == '/en/sections/1/articles/1'
227
+ end
228
+
229
+ it 'appends the pages segments to section_article_path when given page option does not equal 1' do
230
+ section_article_path(@section, @article, :page => 2).should == '/en/sections/1/articles/1/pages/2'
231
+ end
232
+
233
+ it 'prepends the current locale to section_article_path' do
234
+ I18n.locale = :de
235
+ section_article_path(@section, @article).should == '/de/sections/1/articles/1'
236
+ end
237
+
238
+ it 'prepends a given locale param to section_article_path' do
239
+ I18n.locale = :de
240
+ section_article_path(@section, @article, :locale => :fi).should == '/fi/sections/1/articles/1'
241
+ end
242
+
243
+ it 'does not prepend a locale to section_article_path if given locale is false' do
244
+ section_article_path(@section, @article, :locale => false).should == '/sections/1/articles/1'
245
+ end
246
+
247
+ it 'works for section_article_path with both a locale and page option' do
248
+ section_article_path(@section, @article, :locale => :fi, :page => 2).should == '/fi/sections/1/articles/1/pages/2'
249
+ end
250
+
251
+ it 'should not prepend an invalid locale to section_article_path' do
252
+ section_article_path(@section, @article, :locale => :aa).should == '/sections/1/articles/1'
253
+ end
254
+
255
+ it 'should prepend a longer locale to section_article_path' do
256
+ section_article_path(@section, @article, :locale => 'en-US').should == '/en-US/sections/1/articles/1'
257
+ end
258
+
259
+ it 'should not prepend the default locale when configured not to' do
260
+ RoutingFilter::Locale.include_default_locale = false
261
+ section_article_path(@section, @article, :locale => :en).should == '/sections/1/articles/1'
262
+ end
263
+ end
264
+ end
265
+
266
+ describe 'when used with url_for and an ActivRecord instance' do
267
+ describe "a not nested resource" do
268
+ it 'does not change the url_for result when given page option equals 1' do
269
+ params = @section_params.update :id => @section, :page => 1
270
+ url_for(params).should == 'http://test.host/en/sections/1'
271
+ end
272
+
273
+ it 'appends the pages segments to url_for result when given page option does not equal 1' do
274
+ params = @section_params.update :id => @section, :page => 2
275
+ url_for(params).should == 'http://test.host/en/sections/1/pages/2'
276
+ end
277
+
278
+ it 'prepends the current locale to url_for result' do
279
+ I18n.locale = :de
280
+ params = @section_params.update :id => @section
281
+ url_for(params).should == 'http://test.host/de/sections/1'
282
+ end
283
+
284
+ it 'prepends a given locale param url_for result' do
285
+ I18n.locale = :de
286
+ params = @section_params.update :id => @section, :locale => :fi
287
+ url_for(params).should == 'http://test.host/fi/sections/1'
288
+ end
289
+
290
+ it 'does not prepend a locale to url_for result if given locale is false' do
291
+ params = @section_params.update :id => @section, :locale => false
292
+ url_for(params).should == 'http://test.host/sections/1'
293
+ end
294
+
295
+ it 'works for url_for result with both a locale and page option' do
296
+ params = @section_params.update :id => @section, :locale => :fi, :page => 2
297
+ url_for(params).should == 'http://test.host/fi/sections/1/pages/2'
298
+ end
299
+
300
+ it 'should not prepend an invalid locale to section_path' do
301
+ params = @section_params.update :id => @section, :locale => :aa
302
+ url_for(params).should == 'http://test.host/sections/1'
303
+ end
304
+
305
+ it 'should prepend a longer locale to section_path' do
306
+ params = @section_params.update :id => @section, :locale => 'en-US'
307
+ url_for(params).should == 'http://test.host/en-US/sections/1'
308
+ end
309
+
310
+ it 'should not prepend the default locale when configured not to' do
311
+ RoutingFilter::Locale.include_default_locale = false
312
+ params = @section_params.update :id => @section, :locale => :en
313
+ url_for(params).should == 'http://test.host/sections/1'
314
+ end
315
+ end
316
+
317
+ describe "a nested resource" do
318
+ it 'does not change the url_for result when given page option equals 1' do
319
+ params = @article_params.update :section_id => @section, :id => @article, :page => 1
320
+ url_for(params).should == 'http://test.host/en/sections/1/articles/1'
321
+ end
322
+
323
+ it 'appends the pages segments to url_for result when given page option does not equal 1' do
324
+ params = @article_params.update :section_id => @section, :id => @article, :page => 2
325
+ url_for(params).should == 'http://test.host/en/sections/1/articles/1/pages/2'
326
+ end
327
+
328
+ it 'prepends the current locale to url_for result' do
329
+ I18n.locale = :de
330
+ params = @article_params.update :section_id => @section, :id => @article
331
+ url_for(params).should == 'http://test.host/de/sections/1/articles/1'
332
+ end
333
+
334
+ it 'prepends a given locale param to url_for result' do
335
+ I18n.locale = :de
336
+ params = @article_params.update :section_id => @section, :id => @article, :locale => :fi
337
+ url_for(params).should == 'http://test.host/fi/sections/1/articles/1'
338
+ end
339
+
340
+ it 'does not prepend a locale to url_for result if given locale is false' do
341
+ params = @article_params.update :section_id => @section, :id => @article, :locale => false
342
+ url_for(params).should == 'http://test.host/sections/1/articles/1'
343
+ end
344
+
345
+ it 'works for url_for result with both a locale and page option' do
346
+ params = @article_params.update :section_id => @section, :id => @article, :locale => :fi, :page => 2
347
+ url_for(params).should == 'http://test.host/fi/sections/1/articles/1/pages/2'
348
+ end
349
+
350
+ it 'should not prepend an invalid locale to url_for result' do
351
+ params = @article_params.update :section_id => @section, :id => @article, :locale => :aa
352
+ url_for(params).should == 'http://test.host/sections/1/articles/1'
353
+ end
354
+
355
+ it 'should prepend a longer locale to section_article_path' do
356
+ params = @article_params.update :section_id => @section, :id => @article, :locale => 'en-US'
357
+ url_for(params).should == 'http://test.host/en-US/sections/1/articles/1'
358
+ end
359
+
360
+ it 'should not prepend the default locale when configured not to' do
361
+ RoutingFilter::Locale.include_default_locale = false
362
+ params = @article_params.update :section_id => @section, :id => @article, :locale => :en
363
+ url_for(params).should == 'http://test.host/sections/1/articles/1'
364
+ end
365
+ end
366
+ end
367
+ end
@@ -0,0 +1,19 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ describe 'RoutingFilter::Pagination' do
4
+ include RoutingFilterHelpers
5
+
6
+ before :each do
7
+ setup_environment(:pagination)
8
+ end
9
+
10
+ describe 'url generation' do
11
+ it 'appends the segments /pages/:page to the generated path' do
12
+ section_path(1, :page => 2).should == '/sections/1/pages/2'
13
+ end
14
+
15
+ it 'appends the segments /pages/:page to the generated path excluding http get params' do
16
+ section_path(1, :page => 2, :foo => 'bar').should == '/sections/1/pages/2?foo=bar'
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,76 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ describe 'RoutingFilter', 'url recognition' do
4
+ include RoutingFilterHelpers
5
+
6
+ before :each do
7
+ setup_environment :locale, :pagination
8
+ end
9
+
10
+ it 'recognizes the path /de/sections/1 and sets the :locale param' do
11
+ should_recognize_path '/de/sections/1', @section_params.update(:locale => 'de')
12
+ end
13
+
14
+ it 'recognizes the path /sections/1/pages/1 and sets the :page param' do
15
+ should_recognize_path '/sections/1/pages/1', @section_params.update(:page => 1)
16
+ end
17
+
18
+ it 'recognizes the path /de/sections/1/pages/1 and sets the :locale param' do
19
+ should_recognize_path '/de/sections/1/pages/1', @section_params.update(:locale => 'de', :page => 1)
20
+ end
21
+
22
+ it 'recognizes the path /sections/1/articles/1 and sets the :locale param' do
23
+ should_recognize_path '/sections/1/articles/1', @article_params
24
+ end
25
+
26
+ it 'recognizes the path /de/sections/1/articles/1 and sets the :locale param' do
27
+ should_recognize_path '/de/sections/1/articles/1', @article_params.update(:locale => 'de')
28
+ end
29
+
30
+ it 'recognizes the path /de/sections/1/articles/1/pages/1 and sets the :locale param' do
31
+ should_recognize_path '/de/sections/1/articles/1/pages/1', @article_params.update(:locale => 'de', :page => 1)
32
+ end
33
+
34
+ it 'recognizes the path /sections/1 and does not set a :locale param' do
35
+ should_recognize_path '/sections/1', @section_params
36
+ end
37
+
38
+ it 'recognizes the path /sections/1 and does not set a :page param' do
39
+ should_recognize_path '/sections/1', @section_params
40
+ end
41
+
42
+ # Test that routing errors are thrown for invalid locales
43
+ it 'does not recognizes the path /aa/sections/1 and does not set a :locale param' do
44
+ begin
45
+ should_recognize_path '/aa/sections/1', @section_params.update(:locale => 'aa')
46
+ false
47
+ rescue ActionController::RoutingError
48
+ true
49
+ end
50
+ end
51
+
52
+ it 'recognizes the path /en-US/sections/1 and sets a :locale param' do
53
+ should_recognize_path '/en-US/sections/1', @section_params.update(:locale => 'en-US')
54
+ end
55
+
56
+ it 'recognizes the path /sections/1/articles/1 and does not set a :locale param' do
57
+ should_recognize_path '/sections/1/articles/1', @article_params
58
+ end
59
+
60
+ it 'recognizes the path /sections/1/articles/1 and does not set a :page param' do
61
+ should_recognize_path '/sections/1/articles/1', @article_params
62
+ end
63
+
64
+ it 'invalid locale: does not recognize the path /aa/sections/1/articles/1 and does not set a :locale param' do
65
+ lambda { @set.recognize_path('/aa/sections/1/articles/1', {}) }.should raise_error(ActionController::RoutingError)
66
+ end
67
+
68
+ it 'recognizes the path /en-US/sections/1/articles/1 and sets a :locale param' do
69
+ should_recognize_path '/en-US/sections/1/articles/1', @article_params.update(:locale => 'en-US')
70
+ end
71
+
72
+ it 'unescapes the path for the filters' do
73
+ @set.should_receive(:recognize_path_without_filtering).with('/sections/motörhead', 'test')
74
+ @set.recognize_path('/sections/mot%C3%B6rhead', 'test')
75
+ end
76
+ end
@@ -0,0 +1,114 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ describe 'RoutingFilter' do
4
+ include RoutingFilterHelpers
5
+
6
+ before :each do
7
+ setup_environment :locale, :pagination
8
+ end
9
+
10
+ def recognize_path(path = '/de/sections/1', options = {})
11
+ @set.recognize_path(path, options)
12
+ end
13
+
14
+ it 'installs filters to the route set' do
15
+ @locale_filter.should be_instance_of(RoutingFilter::Locale)
16
+ @pagination_filter.should be_instance_of(RoutingFilter::Pagination)
17
+ end
18
+
19
+ it 'calls the first filter for route recognition' do
20
+ @locale_filter.should_receive(:around_recognize).and_return :foo => :bar
21
+ recognize_path.should == { :foo => :bar }
22
+ end
23
+
24
+ it 'calls the second filter for route recognition' do
25
+ @pagination_filter.should_receive(:around_recognize).and_return :foo => :bar
26
+ recognize_path.should == { :foo => :bar, :locale => 'de' }
27
+ end
28
+
29
+ it 'calls the first filter for url generation' do
30
+ @locale_filter.should_receive(:around_generate).and_return '/en/sections/1?page=2'
31
+ url_for(:controller => 'sections', :action => 'show', :section_id => 1)
32
+ end
33
+
34
+ it 'calls the second filter for url generation' do
35
+ @pagination_filter.should_receive(:around_generate).and_return '/sections/1?page=2'
36
+ url_for(:controller => 'sections', :action => 'show', :section_id => 1)
37
+ end
38
+
39
+ it 'calls the first filter for named route url_helper' do
40
+ @locale_filter.should_receive(:around_generate).and_return '/en/sections/1'
41
+ section_path(:section_id => 1)
42
+ end
43
+
44
+ it 'calls the filter for named route url_helper with "optimized" generation blocks' do
45
+ # at_least(1) since the inline code comments in ActionController::Routing::RouteSet::NamedRouteCollection#define_url_helper also call us (as of http://github.com/rails/rails/commit/a2270ef2594b97891994848138614657363f2806)
46
+ @locale_filter.should_receive(:around_generate).at_least(1).and_return '/en/sections/1'
47
+ section_path(1)
48
+ end
49
+
50
+ it 'calls the filter for named route polymorphic_path' do
51
+ # at_least(1) since the inline code comments in ActionController::Routing::RouteSet::NamedRouteCollection#define_url_helper also call us (as of http://github.com/rails/rails/commit/a2270ef2594b97891994848138614657363f2806)
52
+ @locale_filter.should_receive(:around_generate).at_least(1).and_return '/en/sections/1'
53
+ section_path(Section.new)
54
+ end
55
+
56
+ # When filters are set up in the order:
57
+ #
58
+ # map.filter :locale
59
+ # map.filter :pagination
60
+ #
61
+ # Then #around_recognize should be first called on the locale filter and then
62
+ # on the pagination filter. Whereas #around_generate should be first called
63
+ # on the pagination filter and then on the locale filter. Right?
64
+
65
+ it 'calls #around_recognize in the expected order' do
66
+ params = { :id => "1", :page => 2, :controller => "sections", :action => "show" }
67
+ @pagination_filter.stub!(:around_recognize).and_return({ :page => 2, :controller => "sections", :action => "show" })
68
+
69
+ recognize_path('/de/sections/1/pages/2')[:locale].should == "de"
70
+ recognize_path('/de/sections/1/pages/2')[:page].should == 2
71
+ end
72
+
73
+ it 'calls #around_generate in the expected order' do
74
+ @locale_filter.stub!(:around_generate).and_return('de/sections/1')
75
+ section_path(1, :page => 2).should == "de/sections/1/pages/2"
76
+ end
77
+
78
+ it 'does not call deactivated filters' do
79
+ with_deactivated_filters(RoutingFilter::Locale) do
80
+ @locale_filter.should_not_receive(:around_generate)
81
+ section_path(Section.new)
82
+ end
83
+ end
84
+
85
+ it 'still calls successors of deactivated filters' do
86
+ with_deactivated_filters(RoutingFilter::Locale) do
87
+ @pagination_filter.should_receive(:around_recognize).and_return :foo => :bar
88
+ recognize_path('/sections/1').should == { :foo => :bar }
89
+ end
90
+ end
91
+
92
+ # chain
93
+
94
+ it 'adds filters in the order they are registered' do
95
+ @set.filters[0].should == @locale_filter
96
+ @set.filters[1].should == @pagination_filter
97
+ end
98
+
99
+ it 'returns the previous filter as a predecessor of a filter' do
100
+ @set.filters.predecessor(@pagination_filter).should == @locale_filter
101
+ end
102
+
103
+ it 'returns the nil as a predecessor of the first filter' do
104
+ @set.filters.successor(@pagination_filter).should be_nil
105
+ end
106
+
107
+ it 'returns the next filter as a successor of a filter' do
108
+ @set.filters.successor(@locale_filter).should == @pagination_filter
109
+ end
110
+
111
+ it 'returns the nil as a successor of the last filter' do
112
+ @set.filters.successor(@pagination_filter).should be_nil
113
+ end
114
+ end
@@ -0,0 +1,4 @@
1
+ --colour
2
+ --format progress
3
+ --loadby mtime
4
+ --reverse
@@ -0,0 +1,108 @@
1
+ $: << File.dirname(__FILE__)
2
+ $: << File.dirname(__FILE__) + '/../lib/'
3
+
4
+ require 'rubygems'
5
+ require 'actionpack'
6
+ require 'activesupport'
7
+ require 'action_controller'
8
+ require 'action_controller/test_process'
9
+ require 'active_support/vendor'
10
+ require 'spec'
11
+
12
+ require 'routing_filter'
13
+ require 'routing_filter/locale'
14
+ require 'routing_filter/pagination'
15
+
16
+ class Site
17
+ end
18
+
19
+ class Section
20
+ def id; 1 end
21
+ alias :to_param :id
22
+ def type; 'Section' end
23
+ def path; 'section' end
24
+ end
25
+
26
+ class Article
27
+ def to_param; 1 end
28
+ end
29
+
30
+ module RoutingFilterHelpers
31
+ def draw_routes(&block)
32
+ set = returning ActionController::Routing::RouteSet.new do |set|
33
+ class << set; def clear!; end; end
34
+ set.draw &block
35
+ silence_warnings{ ActionController::Routing.const_set 'Routes', set }
36
+ end
37
+ set
38
+ end
39
+
40
+ def instantiate_controller(params)
41
+ returning ActionController::Base.new do |controller|
42
+ request = ActionController::TestRequest.new
43
+ url = ActionController::UrlRewriter.new(request, params)
44
+ controller.stub!(:request).and_return request
45
+ controller.instance_variable_set :@url, url
46
+ controller
47
+ end
48
+ end
49
+
50
+ def should_recognize_path(path, params)
51
+ @set.recognize_path(path, {}).should == params
52
+ end
53
+
54
+ def home_path(*args)
55
+ @controller.send :home_path, *args
56
+ end
57
+
58
+ def home_url(*args)
59
+ @controller.send :home_url, *args
60
+ end
61
+
62
+ def section_path(*args)
63
+ @controller.send :section_path, *args
64
+ end
65
+
66
+ def section_article_path(*args)
67
+ @controller.send :section_article_path, *args
68
+ end
69
+
70
+ def admin_articles_path(*args)
71
+ @controller.send :admin_articles_path, *args
72
+ end
73
+
74
+ def url_for(*args)
75
+ @controller.send :url_for, *args
76
+ end
77
+
78
+ def setup_environment(*filters)
79
+ RoutingFilter::Locale.locales = [:en, 'en-US', :de, :fi, 'en-UK']
80
+ RoutingFilter::Locale.include_default_locale = true
81
+ I18n.default_locale = :en
82
+ I18n.locale = :en
83
+
84
+ @controller = instantiate_controller :locale => 'de', :id => 1
85
+ @set = draw_routes do |map|
86
+ yield map if block_given?
87
+ filters.each { |filter| map.filter filter }
88
+ map.section 'sections/:id.:format', :controller => 'sections', :action => "show"
89
+ map.section_article 'sections/:section_id/articles/:id', :controller => 'articles', :action => "show"
90
+ map.admin_articles 'admin/articles/:id', :controller => 'admin/articles', :action => "index"
91
+ map.home '/', :controller => 'home', :action => 'index'
92
+ end
93
+
94
+ @section_params = {:controller => 'sections', :action => "show", :id => "1"}
95
+ @article_params = {:controller => 'articles', :action => "show", :section_id => "1", :id => "1"}
96
+ @locale_filter = @set.filters.first
97
+ @pagination_filter = @set.filters.last
98
+ end
99
+
100
+ def with_deactivated_filters(*filters, &block)
101
+ states = filters.inject({}) do |states, filter|
102
+ states[filter], filter.active = filter.active, false
103
+ states
104
+ end
105
+ yield
106
+ states.each { |filter, state| filter.active = state }
107
+ end
108
+ end
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: svenfuchs-routing-filter
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Sven Fuchs
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-08-26 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: routing-filter wraps around the complex beast that the Rails routing system is, allowing for unseen flexibility and power in Rails URL recognition and generation.
17
+ email: svenfuchs@artweb-design.de
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README.markdown
24
+ files:
25
+ - .gitignore
26
+ - MIT-LICENSE
27
+ - README.markdown
28
+ - VERSION
29
+ - init.rb
30
+ - lib/routing_filter.rb
31
+ - lib/routing_filter/base.rb
32
+ - lib/routing_filter/force_extension.rb
33
+ - lib/routing_filter/locale.rb
34
+ - lib/routing_filter/pagination.rb
35
+ - spec/force_extension_spec.rb
36
+ - spec/generation_spec.rb
37
+ - spec/pagination_extension_spec.rb
38
+ - spec/recognition_spec.rb
39
+ - spec/routing_filter_spec.rb
40
+ - spec/spec.opts
41
+ - spec/spec_helper.rb
42
+ has_rdoc: false
43
+ homepage: http://github.com/svenfuchs/routing-filter
44
+ licenses:
45
+ post_install_message:
46
+ rdoc_options:
47
+ - --charset=UTF-8
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: "0"
55
+ version:
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: "0"
61
+ version:
62
+ requirements: []
63
+
64
+ rubyforge_project:
65
+ rubygems_version: 1.3.5
66
+ signing_key:
67
+ specification_version: 3
68
+ summary: routing-filter wraps around the complex beast that the Rails routing system is, allowing for unseen flexibility and power in Rails URL recognition and generation.
69
+ test_files:
70
+ - spec/force_extension_spec.rb
71
+ - spec/generation_spec.rb
72
+ - spec/pagination_extension_spec.rb
73
+ - spec/recognition_spec.rb
74
+ - spec/routing_filter_spec.rb
75
+ - spec/spec_helper.rb