-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathroute_soap.rb
More file actions
147 lines (118 loc) · 3.02 KB
/
route_soap.rb
File metadata and controls
147 lines (118 loc) · 3.02 KB
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
141
142
143
144
145
146
147
require "contracts"
require "securerandom"
module RouteSoap
DefaultRouter = Rails.application.routes if defined? Rails
PathLike = -> (_) do
_.respond_to?(:required_names) && _.respond_to?(:spec)
end
RouteLike = -> (_) do
_.respond_to?(:defaults) && _.respond_to?(:path) && _.respond_to?(:verb)
end
RouterLike = -> (_) do
_.respond_to?(:routes)
end
class Route
include Contracts
DEFAULT_BLACKLIST = [
/\/rails\/info/,
/\/rails\/info\/properties/,
/\/rails\/info\/routes/,
]
# Contract RouteLike => Route
def initialize(route, blacklist = [])
@route = route
@blacklist = blacklist + DEFAULT_BLACKLIST
self
end
Contract nil => Bool
def valid?
action && controller && verb && !blacklisted? && true || false
end
Contract nil => String
def controller_action
@controller_action ||= [route.defaults[:controller], route.defaults[:action]].join("#")
end
Contract nil => String
def path
@path ||= String(route_path.spec).gsub("(.:format)", "").tap do |path|
required_params.each do |param, value|
path.gsub!(":#{param}", value) unless param == :format
end
end
end
Contract nil => Hash
def required_params
hash = { format: route.defaults[:format] }.delete_if { |_, v| v.nil? }
@required_params ||= route_path.required_names.reduce(hash) do |acc, param|
acc[param] = SecureRandom.hex(3)
acc
end
end
Contract nil => Symbol
def verb
@verb ||= route.verb.downcase.to_sym
end
private
attr_reader :route
Contract nil => Or[String, nil]
def action
route.defaults[:action]
end
Contract nil => Bool
def blacklisted?
@blacklist.any? { |x| x.match?(path) }
end
Contract nil => Or[String, nil]
def controller
route.defaults[:controller]
end
Contract nil => PathLike
def route_path
route.path
end
end
class Spec
include Contracts
Contract Route => Spec
def initialize(route)
@route = route
self
end
Contract nil => String
def to_s
"it { #{ expectation } #{ result } }"
end
private
attr_reader :route
def expectation
"expect(#{ route.verb }(\"#{ route.path }\")).to"
end
def result
"route_to(\"#{ route.controller_action }\", #{ route.required_params })"
end
end
class Command
class << self
include Contracts
Contract Or[RouterLike, nil] => nil
def run!(router = DefaultRouter)
puts Query.run(router)
end
end
end
class Query
class << self
include Contracts
# Contract Or[RouterLike, nil] => Array[String]
def run(router, blacklist)
Array.new.tap do |lines|
router.routes.each do |route|
Route.new(route, blacklist).tap do |simple_route|
lines << String(Spec.new(simple_route)) if simple_route.valid?
end
end
end
end
end
end
end