-
Notifications
You must be signed in to change notification settings - Fork 85
/
route.rb
140 lines (113 loc) · 3.65 KB
/
route.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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
module ApiTaster
class Route
cattr_accessor :route_set
cattr_accessor :routes
cattr_accessor :mappings
cattr_accessor :supplied_params
cattr_accessor :obsolete_definitions
cattr_accessor :comments
cattr_accessor :metadata
class << self
def map_routes
self.route_set = Rails.application.routes
self.supplied_params = {}
self.obsolete_definitions = []
self.comments = {}
self.metadata = {}
normalise_routes!
begin
Mapper.instance_eval(&self.mappings.call)
rescue
Route.mappings = {}
end
end
def normalise_routes!
@_route_counter = 0
self.routes = []
unless route_set.respond_to?(:routes)
raise ApiTaster::Exception.new('Route definitions are missing, have you defined ApiTaster.routes?')
end
route_set.routes.each do |route|
next if route.app.is_a?(ActionDispatch::Routing::Mapper::Constraints)
next if route.app.is_a?(Sprockets::Environment)
next if route.app == ApiTaster::Engine
if (rack_app = discover_rack_app(route.app)) && rack_app.respond_to?(:routes)
rack_app.routes.routes.each do |rack_route|
self.routes << normalise_route(rack_route, route.path.spec)
end
end
next if route.verb.source.empty?
self.routes << normalise_route(route)
end
self.routes.flatten!
end
def grouped_routes
defined_definitions.group_by { |r| r[:reqs][:controller] }
end
def find(id)
routes.find { |r| r[:id] == id.to_i }
end
def find_by_verb_and_path(verb, path)
routes.find do |r|
r[:path].to_s == path &&
r[:verb].to_s.downcase == verb.to_s.downcase
end
end
def params_for(route)
unless supplied_params.has_key?(route[:id])
return { :undefined => route }
end
supplied_params[route[:id]].collect { |input| split_input(input, route) }
end
def comment_for(route)
unless undefined_route?(route)
self.comments[route[:id].to_i]
end
end
def metadata_for(route)
unless undefined_route?(route)
self.metadata[route[:id].to_i]
end
end
def defined_definitions
routes.reject { |route| undefined_route?(route) }
end
def missing_definitions
routes.select { |route| undefined_route?(route) }
end
private
def undefined_route?(route)
r = params_for(route)
r.is_a?(Hash) && r.has_key?(:undefined)
end
def discover_rack_app(app)
class_name = app.class.name.to_s
if class_name == "ActionDispatch::Routing::Mapper::Constraints"
discover_rack_app(app.app)
elsif class_name !~ /^ActionDispatch::Routing/
app
end
end
def normalise_route(route, path_prefix = nil)
route.verb.source.split('|').map do |verb|
{
:id => @_route_counter+=1,
:name => route.name,
:verb => verb.gsub(/[$^]/, ''),
:path => path_prefix.to_s + route.path.spec.to_s.sub('(.:format)', ''),
:reqs => route.requirements
}
end
end
def split_input(input, route)
url_param_keys = route[:path].scan /:\w+/
url_params = input.reject { |k, v| ! ":#{k}".in?(url_param_keys) }
post_params = input.diff(url_params)
{
:url_params => url_params,
:post_params => post_params
}
end
end
end
end