routing-filter 0.2.1 → 0.2.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.
- 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
|