restapi 0.0.4 → 0.0.5
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.
- data/Gemfile +0 -1
- data/Gemfile.lock +0 -10
- data/README.rdoc +18 -12
- data/app/controllers/restapi/restapis_controller.rb +28 -1
- data/app/views/layouts/restapi/restapi.html.erb +1 -0
- data/app/views/restapi/restapis/_params.html.erb +22 -0
- data/app/views/restapi/restapis/_params_plain.html.erb +16 -0
- data/app/views/restapi/restapis/index.html.erb +5 -5
- data/app/views/restapi/restapis/method.html.erb +8 -4
- data/app/views/restapi/restapis/plain.html.erb +70 -0
- data/app/views/restapi/restapis/resource.html.erb +16 -5
- data/app/views/restapi/restapis/static.html.erb +4 -6
- data/lib/restapi.rb +2 -1
- data/lib/restapi/application.rb +72 -22
- data/lib/restapi/client/generator.rb +104 -0
- data/lib/restapi/client/template/Gemfile.tt +5 -0
- data/lib/restapi/client/template/README.tt +3 -0
- data/lib/restapi/client/template/base.rb.tt +33 -0
- data/lib/restapi/client/template/bin.rb.tt +110 -0
- data/lib/restapi/client/template/cli.rb.tt +25 -0
- data/lib/restapi/client/template/cli_command.rb.tt +129 -0
- data/lib/restapi/client/template/client.rb.tt +10 -0
- data/lib/restapi/client/template/resource.rb.tt +17 -0
- data/lib/restapi/dsl_definition.rb +20 -2
- data/lib/restapi/error_description.rb +8 -2
- data/lib/restapi/extractor.rb +143 -0
- data/lib/restapi/extractor/collector.rb +113 -0
- data/lib/restapi/extractor/recorder.rb +122 -0
- data/lib/restapi/extractor/writer.rb +356 -0
- data/lib/restapi/helpers.rb +10 -5
- data/lib/restapi/markup.rb +12 -12
- data/lib/restapi/method_description.rb +52 -8
- data/lib/restapi/param_description.rb +6 -5
- data/lib/restapi/railtie.rb +1 -1
- data/lib/restapi/resource_description.rb +1 -1
- data/lib/restapi/restapi_module.rb +43 -0
- data/lib/restapi/validator.rb +70 -3
- data/lib/restapi/version.rb +1 -1
- data/lib/tasks/restapi.rake +120 -121
- data/restapi.gemspec +0 -2
- data/spec/controllers/restapis_controller_spec.rb +41 -6
- data/spec/controllers/users_controller_spec.rb +51 -12
- data/spec/dummy/app/controllers/application_controller.rb +0 -2
- data/spec/dummy/app/controllers/twitter_example_controller.rb +4 -9
- data/spec/dummy/app/controllers/users_controller.rb +13 -6
- data/spec/dummy/config/initializers/restapi.rb +7 -0
- data/spec/dummy/doc/restapi_examples.yml +28 -0
- metadata +49 -76
- data/app/helpers/restapi/restapis_helper.rb +0 -31
@@ -0,0 +1,356 @@
|
|
1
|
+
module Restapi
|
2
|
+
module Extractor
|
3
|
+
class Writer
|
4
|
+
|
5
|
+
def initialize(collector)
|
6
|
+
@collector = collector
|
7
|
+
@examples_file = File.join(Rails.root, "doc", "restapi_examples.yml")
|
8
|
+
end
|
9
|
+
|
10
|
+
def write_examples
|
11
|
+
merged_examples = merge_old_new_examples
|
12
|
+
FileUtils.mkdir_p(File.dirname(@examples_file))
|
13
|
+
File.open(@examples_file, "w") do |f|
|
14
|
+
f << YAML.dump(OrderedHash[*merged_examples.sort_by(&:first).flatten(1)])
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def write_docs
|
19
|
+
descriptions = @collector.finalize_descriptions
|
20
|
+
descriptions.each do |_, desc|
|
21
|
+
if desc[:api].empty?
|
22
|
+
logger.warn("REST_API: Couldn't find any path for #{desc_to_s(desc)}")
|
23
|
+
next
|
24
|
+
end
|
25
|
+
self.class.update_action_description(desc[:controller], desc[:action]) do |u|
|
26
|
+
u.update_generated_description desc
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.update_action_description(controller, action)
|
32
|
+
updater = ActionDescriptionUpdater.new(controller, action)
|
33
|
+
yield updater
|
34
|
+
updater.write!
|
35
|
+
rescue ActionDescriptionUpdater::ControllerNotFound
|
36
|
+
logger.warn("REST_API: Couldn't find controller file for #{controller}")
|
37
|
+
rescue ActionDescriptionUpdater::ActionNotFound
|
38
|
+
logger.warn("REST_API: Couldn't find action #{action} in #{controller}")
|
39
|
+
end
|
40
|
+
|
41
|
+
protected
|
42
|
+
|
43
|
+
def desc_to_s(description)
|
44
|
+
"#{description[:controller].name}##{description[:action]}"
|
45
|
+
end
|
46
|
+
|
47
|
+
def ordered_call(call)
|
48
|
+
call = call.stringify_keys
|
49
|
+
ordered_call = OrderedHash.new
|
50
|
+
%w[verb path query request_data response_data code show_in_doc recorded].each do |k|
|
51
|
+
next unless call.has_key?(k)
|
52
|
+
ordered_call[k] = case call[k]
|
53
|
+
when ActiveSupport::HashWithIndifferentAccess
|
54
|
+
JSON.parse(call[k].to_json) # to_hash doesn't work recursively and I'm too lazy to write the recursion:)
|
55
|
+
else
|
56
|
+
call[k]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
return ordered_call
|
60
|
+
end
|
61
|
+
|
62
|
+
def merge_old_new_examples
|
63
|
+
new_examples = self.load_new_examples
|
64
|
+
old_examples = self.load_old_examples
|
65
|
+
merged_examples = []
|
66
|
+
(new_examples.keys + old_examples.keys).uniq.each do |key|
|
67
|
+
if new_examples.has_key?(key)
|
68
|
+
records = new_examples[key]
|
69
|
+
else
|
70
|
+
records = old_examples[key]
|
71
|
+
end
|
72
|
+
merged_examples << [key, records.map { |r| ordered_call(r) } ]
|
73
|
+
end
|
74
|
+
return merged_examples
|
75
|
+
end
|
76
|
+
|
77
|
+
def load_new_examples
|
78
|
+
@collector.records.reduce({}) do |h, (method, calls)|
|
79
|
+
show_in_doc = nil
|
80
|
+
recorded_examples = calls.map do |call|
|
81
|
+
if show_in_doc.nil?
|
82
|
+
show_in_doc = 1 if showable_in_doc?(call.with_indifferent_access)
|
83
|
+
else
|
84
|
+
show_in_doc = 0
|
85
|
+
end
|
86
|
+
example = call.merge(:show_in_doc => show_in_doc.to_i, :recorded => true)
|
87
|
+
example
|
88
|
+
end
|
89
|
+
h.update(method => recorded_examples)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def load_old_examples
|
94
|
+
if File.exists?(@examples_file)
|
95
|
+
return YAML.load(File.read(@examples_file))
|
96
|
+
end
|
97
|
+
return {}
|
98
|
+
end
|
99
|
+
|
100
|
+
def logger
|
101
|
+
self.class.logger
|
102
|
+
end
|
103
|
+
|
104
|
+
def self.logger
|
105
|
+
Extractor.logger
|
106
|
+
end
|
107
|
+
|
108
|
+
def showable_in_doc?(call)
|
109
|
+
# we don't want to mess documentation with too large examples
|
110
|
+
if hash_nodes_count(call["request_data"]) + hash_nodes_count(call["response_data"]) > 100
|
111
|
+
return false
|
112
|
+
else
|
113
|
+
return 1
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def hash_nodes_count(node)
|
118
|
+
case node
|
119
|
+
when Hash
|
120
|
+
1 + (node.values.map { |v| hash_nodes_count(v) }.reduce(:+) || 0)
|
121
|
+
when Array
|
122
|
+
node.map { |v| hash_nodes_count(v) }.reduce(:+) || 1
|
123
|
+
else
|
124
|
+
1
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
|
130
|
+
class ActionDescriptionUpdater
|
131
|
+
|
132
|
+
class ControllerNotFound < Exception; end
|
133
|
+
|
134
|
+
class ActionNotFound < Exception; end
|
135
|
+
|
136
|
+
def initialize(controller, action)
|
137
|
+
@controller = controller
|
138
|
+
@action = action
|
139
|
+
end
|
140
|
+
|
141
|
+
def generated?
|
142
|
+
old_header.include?(Restapi.configuration.generated_doc_disclaimer)
|
143
|
+
end
|
144
|
+
|
145
|
+
def update_apis(apis)
|
146
|
+
new_header = ""
|
147
|
+
new_header << Restapi.configuration.generated_doc_disclaimer << "\n" if generated?
|
148
|
+
new_header << generate_apis_code(apis)
|
149
|
+
new_header << ensure_line_breaks(old_header.lines).reject do |line|
|
150
|
+
line.include?(Restapi.configuration.generated_doc_disclaimer) ||
|
151
|
+
line =~ /^api/
|
152
|
+
end.join
|
153
|
+
overwrite_header(new_header)
|
154
|
+
end
|
155
|
+
|
156
|
+
def update_generated_description(desc)
|
157
|
+
if generated? || old_header.empty?
|
158
|
+
new_header = generate_code(desc)
|
159
|
+
overwrite_header(new_header)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def update(new_header)
|
164
|
+
overwrite_header(new_header)
|
165
|
+
end
|
166
|
+
|
167
|
+
def old_header
|
168
|
+
return @old_header if defined? @old_header
|
169
|
+
@old_header = lines_above_method[/^\s*?#{Regexp.escape(Restapi.configuration.generated_doc_disclaimer)}.*/m]
|
170
|
+
@old_header ||= lines_above_method[/^\s*?\b(api|params|error|example)\b.*/m]
|
171
|
+
@old_header ||= ""
|
172
|
+
@old_header.sub!(/\A\s*\n/,"")
|
173
|
+
@old_header = align_indented(@old_header)
|
174
|
+
end
|
175
|
+
|
176
|
+
def write!
|
177
|
+
File.open(controller_path, "w") { |f| f << @controller_content }
|
178
|
+
@changed=false
|
179
|
+
end
|
180
|
+
|
181
|
+
protected
|
182
|
+
|
183
|
+
def logger
|
184
|
+
Extractor.logger
|
185
|
+
end
|
186
|
+
|
187
|
+
def action_line
|
188
|
+
return @action_line if defined? @action_line
|
189
|
+
@action_line = ensure_line_breaks(controller_content.lines).find_index { |line| line =~ /def \b#{@action}\b/ }
|
190
|
+
raise ActionNotFound unless @action_line
|
191
|
+
@action_line
|
192
|
+
end
|
193
|
+
|
194
|
+
def controller_path
|
195
|
+
@controller_path ||= File.join(Rails.root, "app", "controllers", "#{@controller.controller_path}_controller.rb")
|
196
|
+
end
|
197
|
+
|
198
|
+
def controller_content
|
199
|
+
raise ControllerNotFound.new unless File.exists? controller_path
|
200
|
+
@controller_content ||= File.read(controller_path)
|
201
|
+
end
|
202
|
+
|
203
|
+
def controller_content=(new_content)
|
204
|
+
return if @controller_name == new_content
|
205
|
+
remove_instance_variable("@action_line")
|
206
|
+
remove_instance_variable("@old_header")
|
207
|
+
@controller_content=new_content
|
208
|
+
@changed = true
|
209
|
+
end
|
210
|
+
|
211
|
+
def generate_code(desc)
|
212
|
+
code = "#{Restapi.configuration.generated_doc_disclaimer}\n"
|
213
|
+
code << generate_apis_code(desc[:api])
|
214
|
+
code << generate_params_code(desc[:params])
|
215
|
+
code << generate_errors_code(desc[:errors])
|
216
|
+
return code
|
217
|
+
end
|
218
|
+
|
219
|
+
def generate_apis_code(apis)
|
220
|
+
code = ""
|
221
|
+
apis.sort_by {|a| a[:path] }.each do |api|
|
222
|
+
desc = api[:desc]
|
223
|
+
name = @controller.controller_name.gsub("_", " ")
|
224
|
+
desc ||= case @action.to_s
|
225
|
+
when "show", "create", "update", "destroy"
|
226
|
+
name = name.singularize
|
227
|
+
"#{@action.capitalize} #{name =~ /^[aeiou]/ ? "an" : "a"} #{name}"
|
228
|
+
when "index"
|
229
|
+
"List #{name}"
|
230
|
+
end
|
231
|
+
|
232
|
+
code << "api :#{api[:method]}, \"#{api[:path]}\""
|
233
|
+
code << ", \"#{desc}\"" if desc
|
234
|
+
code << "\n"
|
235
|
+
end
|
236
|
+
return code
|
237
|
+
end
|
238
|
+
|
239
|
+
def generate_params_code(params, indent = "")
|
240
|
+
code = ""
|
241
|
+
params.sort_by {|n,_| n }.each do |(name, desc)|
|
242
|
+
desc[:type] = (desc[:type] && desc[:type].first) || Object
|
243
|
+
code << "#{indent}param"
|
244
|
+
if name =~ /\W/
|
245
|
+
code << " :\"#{name}\""
|
246
|
+
else
|
247
|
+
code << " :#{name}"
|
248
|
+
end
|
249
|
+
code << ", #{desc[:type].inspect}"
|
250
|
+
if desc[:allow_nil]
|
251
|
+
code << ", :allow_nil => true"
|
252
|
+
end
|
253
|
+
if desc[:required]
|
254
|
+
code << ", :required => true"
|
255
|
+
end
|
256
|
+
if desc[:nested]
|
257
|
+
code << " do\n"
|
258
|
+
code << generate_params_code(desc[:nested], indent + " ")
|
259
|
+
code << "#{indent}end"
|
260
|
+
else
|
261
|
+
end
|
262
|
+
code << "\n"
|
263
|
+
end
|
264
|
+
code
|
265
|
+
end
|
266
|
+
|
267
|
+
def generate_errors_code(errors)
|
268
|
+
code = ""
|
269
|
+
errors.sort_by {|e| e[:code] }.each do |error|
|
270
|
+
code << "error :code => #{error[:code]}\n"
|
271
|
+
end
|
272
|
+
code
|
273
|
+
end
|
274
|
+
|
275
|
+
def align_indented(text)
|
276
|
+
shift_left = ensure_line_breaks(text.lines).map { |l| l[/^\s*/].size }.min
|
277
|
+
ensure_line_breaks(text.lines).map { |l| l[shift_left..-1] }.join
|
278
|
+
end
|
279
|
+
|
280
|
+
def overwrite_header(new_header)
|
281
|
+
overwrite_line_from = action_line
|
282
|
+
overwrite_line_to = action_line
|
283
|
+
unless old_header.empty?
|
284
|
+
overwrite_line_from -= ensure_line_breaks(old_header.lines).count
|
285
|
+
end
|
286
|
+
lines = ensure_line_breaks(controller_content.lines).to_a
|
287
|
+
indentation = lines[action_line][/^\s*/]
|
288
|
+
self.controller_content= (lines[0...overwrite_line_from] +
|
289
|
+
[new_header.gsub(/^/,indentation)] +
|
290
|
+
lines[overwrite_line_to..-1]).join
|
291
|
+
end
|
292
|
+
|
293
|
+
# returns all the lines before the method that might contain the restpi descriptions
|
294
|
+
# not bulletproof but working for conventional Ruby code
|
295
|
+
def lines_above_method
|
296
|
+
added_lines = []
|
297
|
+
lines_to_add = []
|
298
|
+
block_level = 0
|
299
|
+
ensure_line_breaks(controller_content.lines).first(action_line).reverse_each do |line|
|
300
|
+
if line =~ /\s*\bend\b\s*/
|
301
|
+
block_level += 1
|
302
|
+
end
|
303
|
+
if block_level > 0
|
304
|
+
lines_to_add << line
|
305
|
+
else
|
306
|
+
added_lines << line
|
307
|
+
end
|
308
|
+
if line =~ /\s*\b(module|class|def)\b /
|
309
|
+
break
|
310
|
+
end
|
311
|
+
if line =~ /do\s*(\|.*?\|)?\s*$/
|
312
|
+
block_level -= 1
|
313
|
+
if block_level == 0
|
314
|
+
added_lines.concat(lines_to_add)
|
315
|
+
lines_to_add = []
|
316
|
+
end
|
317
|
+
end
|
318
|
+
end
|
319
|
+
return added_lines.reverse.join
|
320
|
+
end
|
321
|
+
|
322
|
+
# this method would be totally useless unless some clever guy
|
323
|
+
# desided that it would be great idea to change a behavior of
|
324
|
+
# "".lines method to not include end of lines.
|
325
|
+
#
|
326
|
+
# For more details:
|
327
|
+
# https://github.com/puppetlabs/puppet/blob/0dc44695/lib/puppet/util/monkey_patches.rb
|
328
|
+
def ensure_line_breaks(lines)
|
329
|
+
if lines.to_a.size > 1 && lines.first !~ /\n\Z/
|
330
|
+
lines.map { |l| l !~ /\n\Z/ ? (l << "\n") : l }.to_enum
|
331
|
+
else
|
332
|
+
lines
|
333
|
+
end
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
# Used to keep restapi_examples.yml params in order
|
338
|
+
class OrderedHash < ActiveSupport::OrderedHash
|
339
|
+
|
340
|
+
def to_yaml_type
|
341
|
+
"!tag:yaml.org,2002:map"
|
342
|
+
end
|
343
|
+
|
344
|
+
def to_yaml(opts = {})
|
345
|
+
YAML.quick_emit(self, opts) do |out|
|
346
|
+
out.map(taguri) do |map|
|
347
|
+
each do |k, v|
|
348
|
+
map.add(k, v)
|
349
|
+
end
|
350
|
+
end
|
351
|
+
end
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
end
|
356
|
+
end
|
data/lib/restapi/helpers.rb
CHANGED
@@ -4,16 +4,21 @@ module Restapi
|
|
4
4
|
Restapi.configuration.markup.to_html(text.strip_heredoc)
|
5
5
|
end
|
6
6
|
|
7
|
+
attr_accessor :url_prefix
|
8
|
+
|
7
9
|
def full_url(path)
|
8
|
-
unless @
|
9
|
-
@
|
10
|
+
unless @url_prefix
|
11
|
+
@url_prefix = ""
|
10
12
|
if rails_prefix = ENV["RAILS_RELATIVE_URL_ROOT"]
|
11
|
-
@
|
13
|
+
@url_prefix << rails_prefix
|
12
14
|
end
|
13
|
-
@
|
15
|
+
@url_prefix << Restapi.configuration.doc_base_url
|
14
16
|
end
|
15
17
|
path = path.sub(/^\//,"")
|
16
|
-
"#{@
|
18
|
+
ret = "#{@url_prefix}/#{path}"
|
19
|
+
ret.insert(0,"/") unless ret =~ /\A[.\/]/
|
20
|
+
ret.sub!(/\/*\Z/,"")
|
21
|
+
ret
|
17
22
|
end
|
18
23
|
end
|
19
24
|
end
|
data/lib/restapi/markup.rb
CHANGED
@@ -1,40 +1,40 @@
|
|
1
1
|
module Restapi
|
2
|
-
|
2
|
+
|
3
3
|
module Markup
|
4
|
-
|
4
|
+
|
5
5
|
class RDoc
|
6
|
-
|
6
|
+
|
7
7
|
def initialize
|
8
8
|
require 'rdoc'
|
9
9
|
require 'rdoc/markup/to_html'
|
10
10
|
@rdoc ||= ::RDoc::Markup::ToHtml.new
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
def to_html(text)
|
14
14
|
@rdoc.convert(text)
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
class Markdown
|
20
|
-
|
20
|
+
|
21
21
|
def initialize
|
22
22
|
require 'redcarpet'
|
23
23
|
@redcarpet ||= ::Redcarpet::Markdown.new(::Redcarpet::Render::HTML.new)
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
def to_html(text)
|
27
27
|
@redcarpet.render(text)
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
class Textile
|
33
|
-
|
33
|
+
|
34
34
|
def initialize
|
35
35
|
require 'RedCloth'
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
38
|
def to_html(text)
|
39
39
|
RedCloth.new(text).to_html
|
40
40
|
end
|
@@ -21,25 +21,32 @@ module Restapi
|
|
21
21
|
|
22
22
|
end
|
23
23
|
|
24
|
-
attr_reader :errors, :full_description, :method, :resource, :apis, :examples
|
24
|
+
attr_reader :errors, :full_description, :method, :resource, :apis, :examples, :see
|
25
25
|
|
26
26
|
def initialize(method, resource, app)
|
27
27
|
@method = method
|
28
28
|
@resource = resource
|
29
29
|
|
30
30
|
@apis = app.get_api_args
|
31
|
+
@see = app.get_see
|
31
32
|
|
32
33
|
desc = app.get_description || ''
|
33
34
|
@full_description = Restapi.markup_to_html(desc)
|
34
35
|
@errors = app.get_errors
|
35
36
|
@params_ordered = app.get_params
|
36
37
|
@examples = app.get_examples
|
38
|
+
|
39
|
+
@examples += load_recorded_examples
|
37
40
|
|
38
41
|
parent = @resource.controller.superclass
|
39
42
|
if parent != ActionController::Base
|
40
43
|
@parent_resource = parent.controller_name
|
41
44
|
end
|
42
|
-
@resource.add_method(
|
45
|
+
@resource.add_method(id)
|
46
|
+
end
|
47
|
+
|
48
|
+
def id
|
49
|
+
"#{resource._id}##{method}"
|
43
50
|
end
|
44
51
|
|
45
52
|
def params
|
@@ -64,11 +71,7 @@ module Restapi
|
|
64
71
|
end
|
65
72
|
|
66
73
|
def doc_url
|
67
|
-
|
68
|
-
ENV["RAILS_RELATIVE_URL_ROOT"],
|
69
|
-
Restapi.configuration.doc_base_url,
|
70
|
-
"/#{@resource._id}/#{@method}"
|
71
|
-
].join
|
74
|
+
Restapi.full_url("#{@resource._id}/#{@method}")
|
72
75
|
end
|
73
76
|
|
74
77
|
def method_apis_to_json
|
@@ -81,6 +84,20 @@ module Restapi
|
|
81
84
|
end
|
82
85
|
end
|
83
86
|
|
87
|
+
def see_url
|
88
|
+
if @see
|
89
|
+
method_description = Restapi[@see]
|
90
|
+
if method_description.nil?
|
91
|
+
raise ArgumentError.new("Method #{@see} referenced in 'see' does not exist.")
|
92
|
+
end
|
93
|
+
method_description.doc_url
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def see
|
98
|
+
@see
|
99
|
+
end
|
100
|
+
|
84
101
|
def to_json
|
85
102
|
{
|
86
103
|
:doc_url => doc_url,
|
@@ -89,7 +106,9 @@ module Restapi
|
|
89
106
|
:full_description => @full_description,
|
90
107
|
:errors => @errors,
|
91
108
|
:params => params_ordered.map(&:to_json).flatten,
|
92
|
-
:examples => @examples
|
109
|
+
:examples => @examples,
|
110
|
+
:see => @see,
|
111
|
+
:see_url => see_url
|
93
112
|
}
|
94
113
|
end
|
95
114
|
|
@@ -101,6 +120,31 @@ module Restapi
|
|
101
120
|
params.concat(new_params)
|
102
121
|
end
|
103
122
|
|
123
|
+
def load_recorded_examples
|
124
|
+
(Restapi.recorded_examples[id] || []).
|
125
|
+
find_all { |ex| ex["show_in_doc"].to_i > 0 }.
|
126
|
+
sort_by { |ex| ex["show_in_doc"] }.
|
127
|
+
map { |ex| format_example(ex.symbolize_keys) }
|
128
|
+
end
|
129
|
+
|
130
|
+
def format_example_data(data)
|
131
|
+
case data
|
132
|
+
when Array, Hash
|
133
|
+
JSON.pretty_generate(data).gsub(/: \[\s*\]/,": []").gsub(/\{\s*\}/,"{}")
|
134
|
+
else
|
135
|
+
data
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def format_example(ex)
|
140
|
+
example = "#{ex[:verb]} #{ex[:path]}"
|
141
|
+
example << "?#{ex[:query]}" unless ex[:query].blank?
|
142
|
+
example << "\n" << format_example_data(ex[:request_data]).to_s if ex[:request_data]
|
143
|
+
example << "\n" << ex[:code].to_s
|
144
|
+
example << "\n" << format_example_data(ex[:response_data]).to_s if ex[:response_data]
|
145
|
+
example
|
146
|
+
end
|
147
|
+
|
104
148
|
end
|
105
149
|
|
106
150
|
end
|