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.
@@ -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
@@ -0,0 +1,3 @@
1
+ module RoutingFilter
2
+ VERSION = '0.2.2'
3
+ 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