forked from svenfuchs/routing-filter
/
routing_filter.rb
76 lines (67 loc) · 2.86 KB
/
routing_filter.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
module RoutingFilter
mattr_accessor :active
@@active = true
class Chain < Array
def << (filter)
filter.successor = last
super
end
def run(method, *args, &final)
RoutingFilter.active ? last.run(method, *args, &final) : final.call
end
end
end
# allows to install a filter to the route set by calling: map.filter 'locale'
ActionController::Routing::RouteSet::Mapper.class_eval do
def filter(name, options = {})
require "routing_filter/#{name}"
klass = RoutingFilter.const_get name.to_s.camelize
@set.filters << klass.new(options)
end
end
# same here for the optimized url generation in named routes
ActionController::Routing::RouteSet::NamedRouteCollection.class_eval do
# gosh. monkey engineering optimization code
def generate_optimisation_block_with_filtering(*args)
code = generate_optimisation_block_without_filtering *args
if match = code.match(%r(^return (.*) if (.*)))
# returned string must not contain newlines, or we'll spill out of inline code comments in ActionController::Routing::RouteSet::NamedRouteCollection#define_url_helper (as of http://github.com/rails/rails/commit/a2270ef2594b97891994848138614657363f2806)
"returning(#{match[1]}) { |result| ActionController::Routing::Routes.filters.run :around_generate, *args, &lambda{ result } } if #{match[2]}"
end
end
alias_method_chain :generate_optimisation_block, :filtering
end
ActionController::Routing::RouteSet.class_eval do
def clear_with_filtering!
returning clear_without_filtering! do
@filters.clear if @filters
end
end
alias_method_chain :clear!, :filtering
def filters
@filters ||= RoutingFilter::Chain.new
end
def recognize_path_with_filtering(path, env)
path = path.dup # string is frozen due to memoize
filters.run :around_recognize, path, env, &lambda{ recognize_path_without_filtering(path, env) }
end
alias_method_chain :recognize_path, :filtering
def generate_with_filtering(*args)
filters.run :around_generate, args.first, &lambda{ generate_without_filtering(*args) }
end
alias_method_chain :generate, :filtering
# add some useful information to the request environment
# right, this is from jamis buck's excellent article about routes internals
# http://weblog.jamisbuck.org/2006/10/26/monkey-patching-rails-extending-routes-2
# TODO move this ... where?
alias_method :extract_request_environment_without_host, :extract_request_environment unless method_defined? :extract_request_environment_without_host
def extract_request_environment(request)
returning extract_request_environment_without_host(request) do |env|
env.merge! :host => request.host,
:port => request.port,
:host_with_port => request.host_with_port,
:domain => request.domain,
:subdomain => request.subdomains.first
end
end
end