routing-filter 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +2 -0
- data/Gemfile.lock +82 -0
- data/MIT-LICENSE +20 -0
- data/README.markdown +190 -0
- data/lib/routing-filter.rb +1 -0
- data/lib/routing_filter.rb +27 -0
- data/lib/routing_filter/adapters/rails_2.rb +69 -0
- data/lib/routing_filter/adapters/rails_3.rb +71 -0
- data/lib/routing_filter/chain.rb +22 -0
- data/lib/routing_filter/filter.rb +37 -0
- data/lib/routing_filter/filters/extension.rb +76 -0
- data/lib/routing_filter/filters/locale.rb +79 -0
- data/lib/routing_filter/filters/pagination.rb +47 -0
- data/lib/routing_filter/filters/uuid.rb +40 -0
- data/lib/routing_filter/version.rb +3 -0
- data/test/all.rb +1 -0
- data/test/filters/all_filters/generation.rb +42 -0
- data/test/filters/all_filters/recognition.rb +92 -0
- data/test/filters/all_filters_test.rb +25 -0
- data/test/filters/extension_test.rb +54 -0
- data/test/filters/locale_test.rb +69 -0
- data/test/filters/pagination_test.rb +29 -0
- data/test/filters/uuid_test.rb +40 -0
- data/test/rails_3_test.rb +73 -0
- data/test/routes_test.rb +31 -0
- data/test/routing_filter_test.rb +47 -0
- data/test/test_helper.rb +42 -0
- metadata +31 -5
@@ -0,0 +1,22 @@
|
|
1
|
+
module RoutingFilter
|
2
|
+
class Chain < Array
|
3
|
+
def <<(filter)
|
4
|
+
filter.previous, last.next = last, filter if last
|
5
|
+
super
|
6
|
+
end
|
7
|
+
alias push <<
|
8
|
+
|
9
|
+
def unshift(filter)
|
10
|
+
filter.next, first.previous = first, filter if first
|
11
|
+
super
|
12
|
+
end
|
13
|
+
|
14
|
+
def run(method, *args, &final)
|
15
|
+
active? ? first.run(method, *args, &final) : final.call
|
16
|
+
end
|
17
|
+
|
18
|
+
def active?
|
19
|
+
RoutingFilter.active? && !empty?
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module RoutingFilter
|
2
|
+
class Filter
|
3
|
+
attr_accessor :next, :previous, :options
|
4
|
+
|
5
|
+
def initialize(options = {})
|
6
|
+
@options = options
|
7
|
+
end
|
8
|
+
|
9
|
+
def run(method, *args, &block)
|
10
|
+
_next = self.next ? lambda { self.next.run(method, *args, &block) } : block
|
11
|
+
RoutingFilter.active? ? send(method, *args, &_next) : _next.call(*args)
|
12
|
+
end
|
13
|
+
|
14
|
+
def run_reverse(method, *args, &block)
|
15
|
+
_prev = previous ? lambda { previous.run_reverse(method, *args, &block) } : block
|
16
|
+
RoutingFilter.active? ? send(method, *args, &_prev) : _prev.call(*args)
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
def extract_segment!(pattern, path)
|
22
|
+
path.sub!(pattern) { $2 || '' }
|
23
|
+
path.replace('/') if path.empty?
|
24
|
+
$1
|
25
|
+
end
|
26
|
+
|
27
|
+
def prepend_segment!(result, segment)
|
28
|
+
url = result.is_a?(Array) ? result.first : result
|
29
|
+
url.sub!(%r(^(http.?://[^/]*)?(.*))) { "#{$1}/#{segment}#{$2 == '/' ? '' : $2}" }
|
30
|
+
end
|
31
|
+
|
32
|
+
def append_segment!(result, segment)
|
33
|
+
url = result.is_a?(Array) ? result.first : result
|
34
|
+
url.sub!(%r(/?($|\?))) { "/#{segment}#{$1}" }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# The Extension filter chops a file extension off from the end of the
|
2
|
+
# recognized path. When a path is generated the filter re-adds the extension
|
3
|
+
# to the path accordingly.
|
4
|
+
#
|
5
|
+
# incoming url: /de/products/page/1
|
6
|
+
# filtered url: /de/products
|
7
|
+
# params: params[:locale] = 'de'
|
8
|
+
#
|
9
|
+
# You can install the filter like this:
|
10
|
+
#
|
11
|
+
# # in config/routes.rb
|
12
|
+
# Rails.application.routes.draw do
|
13
|
+
# filter :locale
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# To make your named_route helpers or url_for add the pagination segments you
|
17
|
+
# can use:
|
18
|
+
#
|
19
|
+
# products_path(:locale => 'de')
|
20
|
+
# url_for(:products, :locale => 'de'))
|
21
|
+
|
22
|
+
module RoutingFilter
|
23
|
+
class Extension < Filter
|
24
|
+
attr_reader :extension, :exclude
|
25
|
+
|
26
|
+
def initialize(*args)
|
27
|
+
super
|
28
|
+
@exclude = options[:exclude]
|
29
|
+
@extension = options[:extension] || 'html'
|
30
|
+
end
|
31
|
+
|
32
|
+
def around_recognize(path, env, &block)
|
33
|
+
extract_extension!(path) unless excluded?(path)
|
34
|
+
yield(path, env)
|
35
|
+
end
|
36
|
+
|
37
|
+
def around_generate(params, &block)
|
38
|
+
yield.tap do |result|
|
39
|
+
url = result.is_a?(Array) ? result.first : result
|
40
|
+
append_extension!(url) if append_extension?(url)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
protected
|
45
|
+
|
46
|
+
def extract_extension!(path)
|
47
|
+
path.sub!(/\.#{extension}$/, '')
|
48
|
+
$1
|
49
|
+
end
|
50
|
+
|
51
|
+
def append_extension?(url)
|
52
|
+
!(blank?(url) || excluded?(url) || mime_extension?(url))
|
53
|
+
end
|
54
|
+
|
55
|
+
def append_extension!(url)
|
56
|
+
url.replace url.sub(/(\?|$)/, ".#{extension}\\1")
|
57
|
+
end
|
58
|
+
|
59
|
+
def blank?(url)
|
60
|
+
url.blank? || !!url.match(%r(^/(\?|$)))
|
61
|
+
end
|
62
|
+
|
63
|
+
def excluded?(url)
|
64
|
+
case exclude
|
65
|
+
when Regexp
|
66
|
+
url =~ exclude
|
67
|
+
when Proc
|
68
|
+
exclude.call(url)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def mime_extension?(url)
|
73
|
+
url =~ /\.#{Mime::EXTENSION_LOOKUP.keys.join('|')}(\?|$)/
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# The Locale filter extracts segments matching /:locale from the beginning of
|
2
|
+
# the recognized path and exposes the page parameter as params[:page]. When a
|
3
|
+
# path is generated the filter adds the segments to the path accordingly if
|
4
|
+
# the page parameter is passed to the url helper.
|
5
|
+
#
|
6
|
+
# incoming url: /de/products/page/1
|
7
|
+
# filtered url: /de/products
|
8
|
+
# params: params[:locale] = 'de'
|
9
|
+
#
|
10
|
+
# You can install the filter like this:
|
11
|
+
#
|
12
|
+
# # in config/routes.rb
|
13
|
+
# Rails.application.routes.draw do
|
14
|
+
# filter :locale
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# To make your named_route helpers or url_for add the pagination segments you
|
18
|
+
# can use:
|
19
|
+
#
|
20
|
+
# products_path(:locale => 'de')
|
21
|
+
# url_for(:products, :locale => 'de'))
|
22
|
+
|
23
|
+
require 'i18n'
|
24
|
+
|
25
|
+
module RoutingFilter
|
26
|
+
class Locale < Filter
|
27
|
+
@@include_default_locale = true
|
28
|
+
cattr_writer :include_default_locale
|
29
|
+
|
30
|
+
class << self
|
31
|
+
def include_default_locale?
|
32
|
+
@@include_default_locale
|
33
|
+
end
|
34
|
+
|
35
|
+
def locales
|
36
|
+
@@locales ||= I18n.available_locales.map(&:to_sym)
|
37
|
+
end
|
38
|
+
|
39
|
+
def locales=(locales)
|
40
|
+
@@locales = locales.map(&:to_sym)
|
41
|
+
end
|
42
|
+
|
43
|
+
def locales_pattern
|
44
|
+
@@locales_pattern ||= %r(^/(#{self.locales.map { |l| Regexp.escape(l.to_s) }.join('|')})(?=/|$))
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def around_recognize(path, env, &block)
|
49
|
+
locale = extract_segment!(self.class.locales_pattern, path) # remove the locale from the beginning of the path
|
50
|
+
yield.tap do |params| # invoke the given block (calls more filters and finally routing)
|
51
|
+
params[:locale] = locale if locale # set recognized locale to the resulting params hash
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def around_generate(params, &block)
|
56
|
+
locale = params.delete(:locale) # extract the passed :locale option
|
57
|
+
locale = I18n.locale if locale.nil? # default to I18n.locale when locale is nil (could also be false)
|
58
|
+
locale = nil unless valid_locale?(locale) # reset to no locale when locale is not valid
|
59
|
+
|
60
|
+
yield.tap do |result|
|
61
|
+
prepend_segment!(result, locale) if prepend_locale?(locale)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
protected
|
66
|
+
|
67
|
+
def valid_locale?(locale)
|
68
|
+
locale && self.class.locales.include?(locale.to_sym)
|
69
|
+
end
|
70
|
+
|
71
|
+
def default_locale?(locale)
|
72
|
+
locale && locale.to_sym == I18n.default_locale.to_sym
|
73
|
+
end
|
74
|
+
|
75
|
+
def prepend_locale?(locale)
|
76
|
+
locale && (self.class.include_default_locale? || !default_locale?(locale))
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# The Pagination filter extracts segments matching /page/:page from the end of
|
2
|
+
# the recognized url and exposes the page parameter as params[:page]. When a
|
3
|
+
# url is generated the filter adds the segments to the url accordingly if the
|
4
|
+
# page parameter is passed to the url helper.
|
5
|
+
#
|
6
|
+
# incoming url: /products/page/1
|
7
|
+
# filtered url: /products
|
8
|
+
# params: params[:page] = 1
|
9
|
+
#
|
10
|
+
# You can install the filter like this:
|
11
|
+
#
|
12
|
+
# # in config/routes.rb
|
13
|
+
# Rails.application.routes.draw do
|
14
|
+
# filter :pagination
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# To make your named_route helpers or url_for add the pagination segments you
|
18
|
+
# can use:
|
19
|
+
#
|
20
|
+
# products_path(:page => 1)
|
21
|
+
# url_for(:products, :page => 1)
|
22
|
+
|
23
|
+
module RoutingFilter
|
24
|
+
class Pagination < Filter
|
25
|
+
PAGINATION_SEGMENT = %r(/page/([\d]+)/?$)
|
26
|
+
|
27
|
+
def around_recognize(path, env, &block)
|
28
|
+
page = extract_segment!(PAGINATION_SEGMENT, path)
|
29
|
+
yield(path, env).tap do |params|
|
30
|
+
params[:page] = page.to_i if page
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def around_generate(params, &block)
|
35
|
+
page = params.delete(:page)
|
36
|
+
yield.tap do |result|
|
37
|
+
append_segment!(result, "page/#{page}") if append_page?(page)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
protected
|
42
|
+
|
43
|
+
def append_page?(page)
|
44
|
+
page && page.to_i != 1
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# The Uuid filter extracts an UUID segment from the beginning of the recognized
|
2
|
+
# path and exposes the page parameter as params[:page]. When a path is generated
|
3
|
+
# the filter adds the segments to the path accordingly if the page parameter is
|
4
|
+
# passed to the url helper.
|
5
|
+
#
|
6
|
+
# incoming url: /d00fbbd1-82b6-4c1a-a57d-098d529d6854/product/1
|
7
|
+
# filtered url: /product/1
|
8
|
+
# params: params[:uuid] = 'd00fbbd1-82b6-4c1a-a57d-098d529d6854'
|
9
|
+
#
|
10
|
+
# You can install the filter like this:
|
11
|
+
#
|
12
|
+
# # in config/routes.rb
|
13
|
+
# Rails.application.routes.draw do
|
14
|
+
# filter :uuid
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# To make your named_route helpers or url_for add the uuid segment you can use:
|
18
|
+
#
|
19
|
+
# product_path(:uuid => uuid)
|
20
|
+
# url_for(product, :uuid => uuid)
|
21
|
+
|
22
|
+
module RoutingFilter
|
23
|
+
class Uuid < Filter
|
24
|
+
UUID_SEGMENT = %r(^/?([a-z\d]{8}\-[a-z\d]{4}\-[a-z\d]{4}\-[a-z\d]{4}\-[a-z\d]{12})(/)?)
|
25
|
+
|
26
|
+
def around_recognize(path, env, &block)
|
27
|
+
uuid = extract_segment!(UUID_SEGMENT, path)
|
28
|
+
yield.tap do |params|
|
29
|
+
params[:uuid] = uuid if uuid
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def around_generate(params, &block)
|
34
|
+
uuid = params.delete(:uuid)
|
35
|
+
yield.tap do |result|
|
36
|
+
prepend_segment!(result, uuid) if uuid
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/test/all.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Dir[File.expand_path('../**/*_test.rb', __FILE__)].each { |file| require file }
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Generation
|
2
|
+
test 'generates the path /some.html (extension)' do
|
3
|
+
params = self.params
|
4
|
+
assert_equal '/some.html', routes.generate(params)
|
5
|
+
end
|
6
|
+
|
7
|
+
# extension with any
|
8
|
+
|
9
|
+
test 'generates the path /de/some (extension, locale)' do
|
10
|
+
params = self.params.merge(:locale => 'de')
|
11
|
+
assert_equal '/de/some.html', routes.generate(params)
|
12
|
+
end
|
13
|
+
|
14
|
+
test 'generates the path /some/page/2 (extension, pagination)' do
|
15
|
+
params = self.params.merge(:page => 2)
|
16
|
+
assert_equal '/some/page/2.html', routes.generate(params)
|
17
|
+
end
|
18
|
+
|
19
|
+
test 'generates the path /:uuid/some (extension, uuid)' do
|
20
|
+
params = self.params.merge(:uuid => uuid)
|
21
|
+
assert_equal "/#{uuid}/some.html", routes.generate(params)
|
22
|
+
end
|
23
|
+
|
24
|
+
# extension, locale with any
|
25
|
+
|
26
|
+
test 'generates the path /de/some/page/2 (extension, locale, pagination)' do
|
27
|
+
params = self.params.merge(:locale => 'de', :page => 2)
|
28
|
+
assert_equal '/de/some/page/2.html', routes.generate(params)
|
29
|
+
end
|
30
|
+
|
31
|
+
test 'generates the path /de/:uuid/some (extension, locale, uuid)' do
|
32
|
+
params = self.params.merge(:locale => 'de', :uuid => uuid)
|
33
|
+
assert_equal "/de/#{uuid}/some.html", routes.generate(params)
|
34
|
+
end
|
35
|
+
|
36
|
+
# all
|
37
|
+
|
38
|
+
test 'generates the path /de/some/page/2 (extension, pagination, uuid)' do
|
39
|
+
params = self.params.merge(:locale => 'de', :page => 2, :uuid => uuid)
|
40
|
+
assert_equal "/de/#{uuid}/some/page/2.html", routes.generate(params)
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
module Recognition
|
2
|
+
# 1 filter
|
3
|
+
|
4
|
+
test 'recognizes the path /some.html (extension)' do
|
5
|
+
params = self.params
|
6
|
+
assert_equal params, routes.recognize_path('/some.html')
|
7
|
+
end
|
8
|
+
|
9
|
+
test 'recognizes the path /de/some (locale)' do
|
10
|
+
params = self.params.merge(:locale => 'de')
|
11
|
+
assert_equal params, routes.recognize_path('/de/some')
|
12
|
+
end
|
13
|
+
|
14
|
+
test 'recognizes the path /some/page/2 (pagination)' do
|
15
|
+
params = self.params.merge(:page => 2)
|
16
|
+
assert_equal params, routes.recognize_path('/some/page/2')
|
17
|
+
end
|
18
|
+
|
19
|
+
test 'recognizes the path /:uuid/some (uuid)' do
|
20
|
+
params = self.params.merge(:uuid => uuid)
|
21
|
+
assert_equal params, routes.recognize_path("/#{uuid}/some")
|
22
|
+
end
|
23
|
+
|
24
|
+
# extension with any
|
25
|
+
|
26
|
+
test 'recognizes the path /de/some.html (extension, locale)' do
|
27
|
+
params = self.params.merge(:locale => 'de')
|
28
|
+
assert_equal params, routes.recognize_path('/de/some.html')
|
29
|
+
end
|
30
|
+
|
31
|
+
test 'recognizes the path /some/page/2.html (extension, pagination)' do
|
32
|
+
params = self.params.merge(:page => 2)
|
33
|
+
assert_equal params, routes.recognize_path('/some/page/2.html')
|
34
|
+
end
|
35
|
+
|
36
|
+
test 'recognizes the path /:uuid/some.html (extension, uuid)' do
|
37
|
+
params = self.params.merge(:uuid => uuid)
|
38
|
+
assert_equal params, routes.recognize_path("/#{uuid}/some.html")
|
39
|
+
end
|
40
|
+
|
41
|
+
# locale with any
|
42
|
+
|
43
|
+
test 'recognizes the path /de/some/page/2 (locale, pagination)' do
|
44
|
+
params = self.params.merge(:locale => 'de', :page => 2)
|
45
|
+
assert_equal params, routes.recognize_path('/de/some/page/2')
|
46
|
+
end
|
47
|
+
|
48
|
+
test 'recognizes the path /de/:uuid/some (locale, uuid)' do
|
49
|
+
params = self.params.merge(:locale => 'de', :uuid => uuid)
|
50
|
+
assert_equal params, routes.recognize_path("/de/#{uuid}/some")
|
51
|
+
end
|
52
|
+
|
53
|
+
# pagination with any
|
54
|
+
|
55
|
+
test 'recognizes the path /:uuid/some/page/2 (pagination, uuid)' do
|
56
|
+
params = self.params.merge(:page => 2, :uuid => uuid)
|
57
|
+
assert_equal params, routes.recognize_path("/#{uuid}/some/page/2")
|
58
|
+
end
|
59
|
+
|
60
|
+
# extension, locale with any
|
61
|
+
|
62
|
+
test 'recognizes the path /de/some/page/2.html (extension, locale, pagination)' do
|
63
|
+
params = self.params.merge(:locale => 'de', :page => 2)
|
64
|
+
assert_equal params, routes.recognize_path("/de/some/page/2.html")
|
65
|
+
end
|
66
|
+
|
67
|
+
test 'recognizes the path /de/:uuid/some.html (extension, locale, uuid)' do
|
68
|
+
params = self.params.merge(:locale => 'de', :uuid => uuid)
|
69
|
+
assert_equal params, routes.recognize_path("/de/#{uuid}/some.html")
|
70
|
+
end
|
71
|
+
|
72
|
+
# extension, pagination with any
|
73
|
+
|
74
|
+
test 'recognizes the path /some/page/2.html (extension, pagination, uuid)' do
|
75
|
+
params = self.params.merge(:page => 2, :uuid => uuid)
|
76
|
+
assert_equal params, routes.recognize_path("/#{uuid}/some/page/2.html")
|
77
|
+
end
|
78
|
+
|
79
|
+
# locale, pagination with any
|
80
|
+
|
81
|
+
test 'recognizes the path /de/some/page/2 (locale, pagination, uuid)' do
|
82
|
+
params = self.params.merge(:locale => 'de', :page => 2, :uuid => uuid)
|
83
|
+
assert_equal params, routes.recognize_path("/de/#{uuid}/some/page/2")
|
84
|
+
end
|
85
|
+
|
86
|
+
# all
|
87
|
+
|
88
|
+
test 'recognizes the path /de/:uuid/some/page/2.html (extension, locale, pagination, uuid)' do
|
89
|
+
params = self.params.merge(:locale => 'de', :page => 2, :uuid => uuid)
|
90
|
+
assert_equal params, routes.recognize_path("/de/#{uuid}/some/page/2.html")
|
91
|
+
end
|
92
|
+
end
|