power_api 2.0.0 → 2.1.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/Gemfile.lock +71 -85
- data/README.md +15 -281
- data/lib/generators/power_api/controller/controller_generator.rb +0 -28
- data/lib/generators/power_api/exposed_api_config/exposed_api_config_generator.rb +0 -11
- data/lib/generators/power_api/version/version_generator.rb +0 -23
- data/lib/power_api/engine.rb +2 -5
- data/lib/power_api/generator_helper/active_record_resource.rb +0 -14
- data/lib/power_api/generator_helper/rspec_controller_helper.rb +20 -4
- data/lib/power_api/generator_helpers.rb +0 -1
- data/lib/power_api/version.rb +1 -1
- data/lib/power_api.rb +0 -2
- data/power_api.gemspec +0 -3
- data/spec/dummy/spec/lib/power_api/generator_helper/rspec_controller_helper_spec.rb +18 -6
- data/spec/dummy/spec/support/shared_examples/active_record_resource_atrributes.rb +20 -20
- metadata +2 -47
- data/lib/power_api/generator_helper/swagger_helper.rb +0 -468
- data/spec/dummy/spec/lib/power_api/generator_helper/swagger_helper_spec.rb +0 -470
@@ -1,468 +0,0 @@
|
|
1
|
-
# rubocop:disable Metrics/ModuleLength
|
2
|
-
# rubocop:disable Metrics/MethodLength
|
3
|
-
# rubocop:disable Layout/AlignParameters
|
4
|
-
module PowerApi::GeneratorHelper::SwaggerHelper
|
5
|
-
extend ActiveSupport::Concern
|
6
|
-
|
7
|
-
included do
|
8
|
-
include PowerApi::GeneratorHelper::ApiHelper
|
9
|
-
include PowerApi::GeneratorHelper::ResourceHelper
|
10
|
-
include PowerApi::GeneratorHelper::SimpleTokenAuthHelper
|
11
|
-
include PowerApi::GeneratorHelper::TemplateBuilderHelper
|
12
|
-
include PowerApi::GeneratorHelper::ControllerActionsHelper
|
13
|
-
end
|
14
|
-
|
15
|
-
def swagger_helper_path
|
16
|
-
"spec/swagger_helper.rb"
|
17
|
-
end
|
18
|
-
|
19
|
-
def spec_swagger_path
|
20
|
-
"spec/swagger/.gitkeep"
|
21
|
-
end
|
22
|
-
|
23
|
-
def spec_integration_path
|
24
|
-
"spec/integration/.gitkeep"
|
25
|
-
end
|
26
|
-
|
27
|
-
def rswag_ui_initializer_path
|
28
|
-
"config/initializers/rswag-ui.rb"
|
29
|
-
end
|
30
|
-
|
31
|
-
def swagger_schemas_path
|
32
|
-
"spec/swagger/v#{version_number}/schemas/.gitkeep"
|
33
|
-
end
|
34
|
-
|
35
|
-
def swagger_resource_spec_path
|
36
|
-
"spec/integration/api/v#{version_number}/#{resource.plural}_spec.rb"
|
37
|
-
end
|
38
|
-
|
39
|
-
def swagger_version_definition_path
|
40
|
-
"spec/swagger/v#{version_number}/definition.rb"
|
41
|
-
end
|
42
|
-
|
43
|
-
def swagger_resource_schema_path
|
44
|
-
"spec/swagger/v#{version_number}/schemas/#{resource.snake_case}_schema.rb"
|
45
|
-
end
|
46
|
-
|
47
|
-
def rswag_ui_configure_line
|
48
|
-
"Rswag::Ui.configure do |c|\n"
|
49
|
-
end
|
50
|
-
|
51
|
-
def swagger_helper_api_definition_line
|
52
|
-
"config.swagger_docs = {\n"
|
53
|
-
end
|
54
|
-
|
55
|
-
def swagger_definition_line_to_inject_schema
|
56
|
-
/definitions: {/
|
57
|
-
end
|
58
|
-
|
59
|
-
def rswag_ui_initializer_tpl
|
60
|
-
<<~INITIALIZER
|
61
|
-
Rswag::Ui.configure do |c|
|
62
|
-
end
|
63
|
-
INITIALIZER
|
64
|
-
end
|
65
|
-
|
66
|
-
def swagger_helper_tpl
|
67
|
-
<<~SWAGGER
|
68
|
-
require 'rails_helper'
|
69
|
-
|
70
|
-
Dir[::Rails.root.join("spec/swagger/**/schemas/*.rb")].each { |f| require f }
|
71
|
-
Dir[::Rails.root.join("spec/swagger/**/definition.rb")].each { |f| require f }
|
72
|
-
|
73
|
-
RSpec.configure do |config|
|
74
|
-
# Specify a root folder where Swagger JSON files are generated
|
75
|
-
# NOTE: If you're using the rswag-api to serve API descriptions, you'll need
|
76
|
-
# to ensure that it's confiugred to serve Swagger from the same folder
|
77
|
-
config.swagger_root = Rails.root.to_s + '/swagger'
|
78
|
-
|
79
|
-
# Define one or more Swagger documents and provide global metadata for each one
|
80
|
-
# When you run the 'rswag:specs:to_swagger' rake task, the complete Swagger will
|
81
|
-
# be generated at the provided relative path under swagger_root
|
82
|
-
# By default, the operations defined in spec files are added to the first
|
83
|
-
# document below. You can override this behavior by adding a swagger_doc tag to the
|
84
|
-
# the root example_group in your specs, e.g. describe '...', swagger_doc: 'v2/swagger.json'
|
85
|
-
config.swagger_docs = {
|
86
|
-
}
|
87
|
-
end
|
88
|
-
SWAGGER
|
89
|
-
end
|
90
|
-
|
91
|
-
def rswag_ui_swagger_endpoint
|
92
|
-
" c.swagger_endpoint '/api-docs/v#{version_number}/swagger.json', \
|
93
|
-
'API V#{version_number} Docs'\n"
|
94
|
-
end
|
95
|
-
|
96
|
-
def swagger_helper_api_definition
|
97
|
-
content = " 'v#{version_number}/swagger.json' => API_V#{version_number}"
|
98
|
-
content = "#{content}," unless first_version?
|
99
|
-
"#{content}\n"
|
100
|
-
end
|
101
|
-
|
102
|
-
def swagger_definition_tpl
|
103
|
-
<<~DEFINITION
|
104
|
-
API_V#{version_number} = {
|
105
|
-
swagger: '2.0',
|
106
|
-
info: {
|
107
|
-
title: 'API V#{version_number}',
|
108
|
-
version: 'v#{version_number}'
|
109
|
-
},
|
110
|
-
basePath: '/api/v#{version_number}',
|
111
|
-
definitions: {
|
112
|
-
}
|
113
|
-
}
|
114
|
-
DEFINITION
|
115
|
-
end
|
116
|
-
|
117
|
-
def swagger_schema_tpl
|
118
|
-
<<~SCHEMA
|
119
|
-
#{swagger_model_definition_const} = {
|
120
|
-
type: :object,
|
121
|
-
properties: {#{get_swagger_schema_attributes_definitions}
|
122
|
-
},
|
123
|
-
required: [#{get_swagger_schema_attributes_names}
|
124
|
-
]
|
125
|
-
}
|
126
|
-
|
127
|
-
#{swagger_collection_definition_const} = {
|
128
|
-
type: "object",
|
129
|
-
properties: {
|
130
|
-
#{resource.plural}: {
|
131
|
-
type: "array",
|
132
|
-
items: { "$ref" => "#/definitions/#{resource.snake_case}" }
|
133
|
-
}
|
134
|
-
},
|
135
|
-
required: [
|
136
|
-
:#{resource.plural}
|
137
|
-
]
|
138
|
-
}
|
139
|
-
|
140
|
-
#{swagger_resource_definition_const} = {
|
141
|
-
type: "object",
|
142
|
-
properties: {
|
143
|
-
#{resource.snake_case}: { "$ref" => "#/definitions/#{resource.snake_case}" }
|
144
|
-
},
|
145
|
-
required: [
|
146
|
-
:#{resource.snake_case}
|
147
|
-
]
|
148
|
-
}
|
149
|
-
SCHEMA
|
150
|
-
end
|
151
|
-
|
152
|
-
def swagger_definition_entry
|
153
|
-
[
|
154
|
-
"\n #{resource.snake_case}: #{swagger_model_definition_const},",
|
155
|
-
"\n #{resource.plural}_collection: #{swagger_collection_definition_const},",
|
156
|
-
"\n #{resource.snake_case}_resource: #{swagger_resource_definition_const},"
|
157
|
-
].join
|
158
|
-
end
|
159
|
-
|
160
|
-
def swagger_resource_spec_tpl
|
161
|
-
concat_tpl_statements(
|
162
|
-
"require 'swagger_helper'\n",
|
163
|
-
concat_tpl_statements(
|
164
|
-
spec_tpl_initial_describe_line,
|
165
|
-
spec_tpl_authenticated_resource,
|
166
|
-
spec_tpl_let_parent_resource,
|
167
|
-
spec_tpl_collection_path_statements,
|
168
|
-
spec_tpl_resource_path_statements,
|
169
|
-
"end\n"
|
170
|
-
)
|
171
|
-
)
|
172
|
-
end
|
173
|
-
|
174
|
-
private
|
175
|
-
|
176
|
-
def spec_tpl_initial_describe_line
|
177
|
-
"describe 'API V#{version_number} #{resource.plural_titleized}', \
|
178
|
-
swagger_doc: 'v#{version_number}/swagger.json' do"
|
179
|
-
end
|
180
|
-
|
181
|
-
def spec_tpl_authenticated_resource
|
182
|
-
return unless authenticated_resource?
|
183
|
-
|
184
|
-
res_name = authenticated_resource.snake_case
|
185
|
-
concat_tpl_statements(
|
186
|
-
"let(:#{res_name}) { create(:#{res_name}) }",
|
187
|
-
"let(:#{res_name}_email) { #{res_name}.email }",
|
188
|
-
"let(:#{res_name}_token) { #{res_name}.authentication_token }\n"
|
189
|
-
)
|
190
|
-
end
|
191
|
-
|
192
|
-
def spec_tpl_collection_path_statements
|
193
|
-
return unless collection_actions?
|
194
|
-
|
195
|
-
concat_tpl_statements(
|
196
|
-
"path '/#{spec_tpl_collection_path}' do",
|
197
|
-
spec_tpl_parent_resource_parameter,
|
198
|
-
spec_tpl_authenticated_resource_params,
|
199
|
-
spec_tpl_index,
|
200
|
-
spec_tpl_create,
|
201
|
-
"end\n"
|
202
|
-
)
|
203
|
-
end
|
204
|
-
|
205
|
-
def spec_tpl_collection_path
|
206
|
-
return resource.plural unless parent_resource?
|
207
|
-
|
208
|
-
"#{parent_resource.plural}/{#{parent_resource.id}}/#{resource.plural}"
|
209
|
-
end
|
210
|
-
|
211
|
-
def spec_tpl_resource_path_statements
|
212
|
-
return unless resource_actions?
|
213
|
-
|
214
|
-
concat_tpl_statements(
|
215
|
-
"path '/#{resource.plural}/{id}' do",
|
216
|
-
spec_tpl_authenticated_resource_params,
|
217
|
-
spec_tpl_let_existent_resource,
|
218
|
-
spec_tpl_show,
|
219
|
-
spec_tpl_update,
|
220
|
-
spec_tpl_destroy,
|
221
|
-
"end\n"
|
222
|
-
)
|
223
|
-
end
|
224
|
-
|
225
|
-
def spec_tpl_let_existent_resource
|
226
|
-
statement = ["let(:existent_#{resource.snake_case}) { create(:#{resource.snake_case}"]
|
227
|
-
load_owner_resource_option(statement)
|
228
|
-
|
229
|
-
concat_tpl_statements(
|
230
|
-
"parameter name: :id, in: :path, type: :integer\n",
|
231
|
-
"#{statement.join(', ')}) }",
|
232
|
-
"let(:id) { existent_#{resource.snake_case}.id }\n"
|
233
|
-
)
|
234
|
-
end
|
235
|
-
|
236
|
-
def spec_tpl_authenticated_resource_params
|
237
|
-
return unless authenticated_resource?
|
238
|
-
|
239
|
-
res_name = authenticated_resource.snake_case
|
240
|
-
concat_tpl_statements(
|
241
|
-
"parameter name: :#{res_name}_email, in: :query, type: :string",
|
242
|
-
"parameter name: :#{res_name}_token, in: :query, type: :string\n"
|
243
|
-
)
|
244
|
-
end
|
245
|
-
|
246
|
-
def spec_tpl_index
|
247
|
-
return unless index?
|
248
|
-
|
249
|
-
concat_tpl_statements(
|
250
|
-
"get 'Retrieves #{resource.plural_titleized}' do",
|
251
|
-
"description 'Retrieves all the #{resource.plural}'",
|
252
|
-
"produces 'application/json'\n",
|
253
|
-
"let(:collection_count) { 5 }",
|
254
|
-
"let(:expected_collection_count) { collection_count }\n",
|
255
|
-
"before { #{spec_tpl_index_creation_list} }",
|
256
|
-
"response '200', '#{resource.plural_titleized} retrieved' do",
|
257
|
-
"schema('$ref' => '#/definitions/#{resource.plural}_collection')\n",
|
258
|
-
"run_test! do |response|",
|
259
|
-
"expect(JSON.parse(response.body)['#{resource.plural}'].count).to eq(expected_collection_count)",
|
260
|
-
"end",
|
261
|
-
"end\n",
|
262
|
-
spec_tpl_invalid_credentials,
|
263
|
-
"end\n"
|
264
|
-
)
|
265
|
-
end
|
266
|
-
|
267
|
-
def spec_tpl_index_creation_list
|
268
|
-
statement = ["create_list(:#{resource.snake_case}, collection_count"]
|
269
|
-
load_owner_resource_option(statement)
|
270
|
-
statement.join(', ') + ')'
|
271
|
-
end
|
272
|
-
|
273
|
-
def load_owner_resource_option(statement)
|
274
|
-
if parent_resource?
|
275
|
-
statement << "#{parent_resource.snake_case}: #{parent_resource.snake_case}"
|
276
|
-
end
|
277
|
-
|
278
|
-
if owned_by_authenticated_resource?
|
279
|
-
statement << "#{authenticated_resource.snake_case}: #{authenticated_resource.snake_case}"
|
280
|
-
end
|
281
|
-
end
|
282
|
-
|
283
|
-
def spec_tpl_create
|
284
|
-
return unless create?
|
285
|
-
|
286
|
-
concat_tpl_statements(
|
287
|
-
"post 'Creates #{resource.titleized}' do",
|
288
|
-
"description 'Creates #{resource.titleized}'",
|
289
|
-
"consumes 'application/json'",
|
290
|
-
"produces 'application/json'",
|
291
|
-
"parameter(name: :#{resource.snake_case}, in: :body)\n",
|
292
|
-
"response '201', '#{resource.snake_case} created' do",
|
293
|
-
"let(:#{resource.snake_case}) do",
|
294
|
-
"{#{resource_params}}",
|
295
|
-
"end\n",
|
296
|
-
"run_test!",
|
297
|
-
"end\n",
|
298
|
-
spec_tpl_create_invalid_attrs_test,
|
299
|
-
spec_tpl_invalid_credentials(with_body: true),
|
300
|
-
"end\n"
|
301
|
-
)
|
302
|
-
end
|
303
|
-
|
304
|
-
def spec_tpl_parent_resource_parameter
|
305
|
-
return unless parent_resource?
|
306
|
-
|
307
|
-
"parameter name: :#{parent_resource.id}, in: :path, type: :integer"
|
308
|
-
end
|
309
|
-
|
310
|
-
def spec_tpl_let_parent_resource
|
311
|
-
return unless parent_resource?
|
312
|
-
|
313
|
-
concat_tpl_statements(
|
314
|
-
"let(:#{parent_resource.snake_case}) { create(:#{parent_resource.snake_case}) }",
|
315
|
-
"let(:#{parent_resource.id}) { #{parent_resource.snake_case}.id }\n"
|
316
|
-
)
|
317
|
-
end
|
318
|
-
|
319
|
-
def spec_tpl_show
|
320
|
-
return unless show?
|
321
|
-
|
322
|
-
concat_tpl_statements(
|
323
|
-
"get 'Retrieves #{resource.titleized}' do",
|
324
|
-
"produces 'application/json'\n",
|
325
|
-
"response '200', '#{resource.snake_case} retrieved' do",
|
326
|
-
"schema('$ref' => '#/definitions/#{resource.snake_case}_resource')\n",
|
327
|
-
"run_test!",
|
328
|
-
"end\n",
|
329
|
-
"response '404', 'invalid #{resource.snake_case} id' do",
|
330
|
-
"let(:id) { 'invalid' }",
|
331
|
-
"run_test!",
|
332
|
-
"end\n",
|
333
|
-
spec_tpl_invalid_credentials,
|
334
|
-
"end\n"
|
335
|
-
)
|
336
|
-
end
|
337
|
-
|
338
|
-
def spec_tpl_update
|
339
|
-
return unless update?
|
340
|
-
|
341
|
-
concat_tpl_statements(
|
342
|
-
"put 'Updates #{resource.titleized}' do",
|
343
|
-
"description 'Updates #{resource.titleized}'",
|
344
|
-
"consumes 'application/json'",
|
345
|
-
"produces 'application/json'",
|
346
|
-
"parameter(name: :#{resource.snake_case}, in: :body)\n",
|
347
|
-
"response '200', '#{resource.snake_case} updated' do",
|
348
|
-
"let(:#{resource.snake_case}) do",
|
349
|
-
"{#{resource_params}}",
|
350
|
-
"end\n",
|
351
|
-
"run_test!",
|
352
|
-
"end\n",
|
353
|
-
spec_tpl_update_invalid_attrs_test,
|
354
|
-
spec_tpl_invalid_credentials(with_body: true),
|
355
|
-
"end\n"
|
356
|
-
)
|
357
|
-
end
|
358
|
-
|
359
|
-
def spec_tpl_destroy
|
360
|
-
return unless destroy?
|
361
|
-
|
362
|
-
concat_tpl_statements(
|
363
|
-
"delete 'Deletes #{resource.titleized}' do",
|
364
|
-
"produces 'application/json'",
|
365
|
-
"description 'Deletes specific #{resource.snake_case}'\n",
|
366
|
-
"response '204', '#{resource.snake_case} deleted' do",
|
367
|
-
"run_test!",
|
368
|
-
"end\n",
|
369
|
-
"response '404', '#{resource.snake_case} not found' do",
|
370
|
-
"let(:id) { 'invalid' }\n",
|
371
|
-
"run_test!",
|
372
|
-
"end\n",
|
373
|
-
spec_tpl_invalid_credentials,
|
374
|
-
"end\n"
|
375
|
-
)
|
376
|
-
end
|
377
|
-
|
378
|
-
def spec_tpl_invalid_credentials(with_body: false)
|
379
|
-
return unless authenticated_resource?
|
380
|
-
|
381
|
-
authenticated_resource_name = authenticated_resource.snake_case
|
382
|
-
concat_tpl_statements(
|
383
|
-
"response '401', '#{authenticated_resource_name} unauthorized' do",
|
384
|
-
with_body ? "let(:#{resource.snake_case}) { {} }" : nil,
|
385
|
-
"let(:user_token) { 'invalid' }\n",
|
386
|
-
"run_test!",
|
387
|
-
"end\n"
|
388
|
-
)
|
389
|
-
end
|
390
|
-
|
391
|
-
def spec_tpl_update_invalid_attrs_test
|
392
|
-
spec_tpl_create_invalid_attrs_test
|
393
|
-
end
|
394
|
-
|
395
|
-
def spec_tpl_create_invalid_attrs_test
|
396
|
-
return if resource.required_resource_attributes.blank?
|
397
|
-
|
398
|
-
concat_tpl_statements(
|
399
|
-
"response '400', 'invalid attributes' do",
|
400
|
-
"let(:#{resource.snake_case}) do",
|
401
|
-
"{#{invalid_resource_params}}",
|
402
|
-
"end\n",
|
403
|
-
"run_test!",
|
404
|
-
"end\n"
|
405
|
-
)
|
406
|
-
end
|
407
|
-
|
408
|
-
def resource_params
|
409
|
-
attrs = if resource.required_resource_attributes.any?
|
410
|
-
resource.required_resource_attributes
|
411
|
-
else
|
412
|
-
resource.optional_resource_attributes
|
413
|
-
end
|
414
|
-
|
415
|
-
for_each_schema_attribute(attrs) do |attr|
|
416
|
-
"#{attr[:name]}: #{attr[:example]},"
|
417
|
-
end
|
418
|
-
end
|
419
|
-
|
420
|
-
def invalid_resource_params
|
421
|
-
return unless resource.required_resource_attributes.any?
|
422
|
-
|
423
|
-
for_each_schema_attribute([resource.required_resource_attributes.first]) do |attr|
|
424
|
-
"#{attr[:name]}: nil,"
|
425
|
-
end
|
426
|
-
end
|
427
|
-
|
428
|
-
def swagger_model_definition_const
|
429
|
-
"#{resource.upcase}_SCHEMA"
|
430
|
-
end
|
431
|
-
|
432
|
-
def swagger_collection_definition_const
|
433
|
-
"#{resource.upcase_plural}_COLLECTION_SCHEMA"
|
434
|
-
end
|
435
|
-
|
436
|
-
def swagger_resource_definition_const
|
437
|
-
"#{resource.upcase}_RESOURCE_SCHEMA"
|
438
|
-
end
|
439
|
-
|
440
|
-
def get_swagger_schema_attributes_definitions
|
441
|
-
for_each_schema_attribute(resource.resource_attributes) do |attr|
|
442
|
-
opts = ["example: #{attr[:example]}"]
|
443
|
-
opts << "'x-nullable': true" unless attr[:required] || attr[:name] == :id
|
444
|
-
opts
|
445
|
-
|
446
|
-
"#{attr[:name]}: { type: :#{attr[:swagger_type]}, #{opts.join(', ')} },"
|
447
|
-
end
|
448
|
-
end
|
449
|
-
|
450
|
-
def get_swagger_schema_attributes_names
|
451
|
-
for_each_schema_attribute(
|
452
|
-
resource.required_resource_attributes(include_id: true)
|
453
|
-
) do |attr|
|
454
|
-
":#{attr[:name]},"
|
455
|
-
end
|
456
|
-
end
|
457
|
-
|
458
|
-
def for_each_schema_attribute(attributes)
|
459
|
-
attributes.inject("") do |memo, attr|
|
460
|
-
memo += "\n"
|
461
|
-
memo += yield(attr)
|
462
|
-
memo
|
463
|
-
end.delete_suffix(",")
|
464
|
-
end
|
465
|
-
end
|
466
|
-
# rubocop:enable Metrics/ModuleLength
|
467
|
-
# rubocop:enable Metrics/MethodLength
|
468
|
-
# rubocop:enable Layout/AlignParameters
|