strikeroff-routing-filter 0.0.2 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +19 -19
- data/Manifest +20 -0
- data/README.markdown +150 -146
- data/Rakefile +21 -0
- data/VERSION +1 -1
- data/lib/routing_filter.rb +94 -94
- data/lib/routing_filter/base.rb +30 -30
- data/lib/routing_filter/force_extension.rb +56 -56
- data/lib/routing_filter/locale.rb +82 -82
- data/lib/routing_filter/pagination.rb +32 -32
- data/routing-filter.gemspec +33 -0
- data/spec/force_extension_spec.rb +65 -65
- data/spec/generation_spec.rb +366 -366
- data/spec/pagination_extension_spec.rb +19 -19
- data/spec/recognition_spec.rb +75 -75
- data/spec/routing_filter_spec.rb +113 -113
- data/spec/spec.opts +4 -4
- data/spec/spec_helper.rb +107 -107
- data/strikeroff-routing-filter.gemspec +33 -0
- metadata +46 -27
- data/.gitignore +0 -2
data/MIT-LICENSE
CHANGED
@@ -1,20 +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
|
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
20
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Manifest
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
init.rb
|
2
|
+
lib/routing_filter/base.rb
|
3
|
+
lib/routing_filter/force_extension.rb
|
4
|
+
lib/routing_filter/locale.rb
|
5
|
+
lib/routing_filter/pagination.rb
|
6
|
+
lib/routing_filter.rb
|
7
|
+
Manifest
|
8
|
+
MIT-LICENSE
|
9
|
+
Rakefile
|
10
|
+
README.markdown
|
11
|
+
routing-filter.gemspec
|
12
|
+
spec/force_extension_spec.rb
|
13
|
+
spec/generation_spec.rb
|
14
|
+
spec/pagination_extension_spec.rb
|
15
|
+
spec/recognition_spec.rb
|
16
|
+
spec/routing_filter_spec.rb
|
17
|
+
spec/spec.opts
|
18
|
+
spec/spec_helper.rb
|
19
|
+
strikeroff-routing-filter.gemspec
|
20
|
+
VERSION
|
data/README.markdown
CHANGED
@@ -1,147 +1,151 @@
|
|
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
|
-
|
121
|
-
# Difference from origin
|
122
|
-
|
123
|
-
1. Locale filter now has option :scip_locale_filter
|
124
|
-
In you routes
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
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
|
+
|
121
|
+
# Difference from origin
|
122
|
+
|
123
|
+
1. Locale filter now has option :scip_locale_filter.
|
124
|
+
In you routes.rb you can write this
|
125
|
+
|
126
|
+
map.change_locale "main/change_locale/:new_locale", :controller=>"main", :action=>"change_locale", :scip_locale_filter=>true
|
127
|
+
|
128
|
+
And locale filter wouldn't add locale to url while generate.
|
129
|
+
|
130
|
+
2. extract_locale! and prepend_locale! methods become class methods aka static. So you can use them outside of gem.
|
131
|
+
|
132
|
+
Usecase:
|
133
|
+
|
134
|
+
For example, to create on page language changer without requests to server. You need only change locale in url.
|
135
|
+
|
136
|
+
Example code:
|
137
|
+
Current locale - :ru,but you need to have a link with locale = :en.
|
138
|
+
|
139
|
+
link_to("EN", url_with_locale(request.request_uri.dup, :en))
|
140
|
+
|
141
|
+
def url_with_locale(url,locale)
|
142
|
+
RoutingFilter::Locale.extract_locale! url
|
143
|
+
RoutingFilter::Locale.prepend_locale! url, locale
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
|
148
|
+
## Etc
|
149
|
+
|
150
|
+
Authors: [Sven Fuchs](http://www.artweb-design.de) <svenfuchs at artweb-design dot de>
|
147
151
|
License: MIT
|
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# Rakefile
|
2
|
+
require 'rubygems'
|
3
|
+
require 'rake'
|
4
|
+
require 'echoe'
|
5
|
+
|
6
|
+
Echoe.new('strikeroff-routing-filter', '0.1.0') do |p|
|
7
|
+
p.description = "strikeroff-routing-filter"
|
8
|
+
p.url = "http://github.com/strikeroff"
|
9
|
+
p.author = "Vesov Ilya"
|
10
|
+
p.email = "strikeroff@gmail.com"
|
11
|
+
p.ignore_pattern = ["tmp/*", "script/*",".svn",".git"]
|
12
|
+
p.need_tar_gz = false
|
13
|
+
p.retain_gemspec = true
|
14
|
+
p.gemspec_name = 'strikeroff-routing-filter.gemspec'
|
15
|
+
p.test_pattern = ["test/**/*_test.rb"]
|
16
|
+
p.rdoc_pattern = ["README", "CHANGELOG", "lib/**/*.rb"]
|
17
|
+
p.rdoc_options << "-c utf-8"
|
18
|
+
p.ignore_pattern = [".gitignore", "doc", ".idea", "*.bat","*.sh"]
|
19
|
+
end
|
20
|
+
|
21
|
+
Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.2
|
1
|
+
0.0.2
|
data/lib/routing_filter.rb
CHANGED
@@ -1,94 +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
|
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
|