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.
data/README.md CHANGED
@@ -126,27 +126,13 @@ After doing this you will get:
126
126
  ```ruby
127
127
  class Api::Exposed::V1::BaseController < Api::BaseController
128
128
  before_action do
129
- self.namespace_for_serializer = ::Api::V1
129
+ self.namespace_for_serializer = ::Api::Exposed::V1
130
130
  end
131
131
  end
132
132
  ```
133
133
  Everything related to version 1 of your API must be included here.
134
134
 
135
135
  - Some initializers:
136
- - `/your_api/config/initializers/rswag-api.rb`:
137
- ```ruby
138
- Rswag::Api.configure do |c|
139
- c.swagger_root = Rails.root.to_s + '/swagger'
140
- end
141
- ```
142
- We use the default options but setting the `your_api/swagger` directory as container for the generated Swagger JSON files.
143
-
144
- - `/your_api/config/initializers/rswag-ui.rb`:
145
- ```ruby
146
- Rswag::Ui.configure do |c|
147
- c.swagger_endpoint '/api-docs/v1/swagger.json', 'API V1 Docs'
148
- end
149
- ```
150
136
  We configure the first version to be seen in the documentation view.
151
137
 
152
138
  - `/your_api/config/initializers/simple_token_authentication.rb`:
@@ -160,56 +146,12 @@ After doing this you will get:
160
146
  ```ruby
161
147
  Rails.application.routes.draw do
162
148
  scope path: '/api' do
163
- api_version(module: 'Api::V1', path: { value: 'v1' }, defaults: { format: 'json' }) do
149
+ api_version(module: 'Api::Exposed::V1', path: { value: 'v1' }, defaults: { format: 'json' }) do
164
150
  end
165
151
  end
166
- mount Rswag::Api::Engine => '/api-docs'
167
- mount Rswag::Ui::Engine => '/api-docs'
168
152
  # ...
169
153
  end
170
154
  ```
171
- Here we create the first version with [Versionist](https://github.com/bploetz/versionist) and mount Rswag.
172
- - A file with the swagger definition for the first version under `/your_api/spec/swagger/v1/definition.rb`
173
- ```ruby
174
- API_V1 = {
175
- swagger: '2.0',
176
- info: {
177
- title: 'API V1',
178
- version: 'v1'
179
- },
180
- basePath: '/api/v1',
181
- definitions: {
182
- }
183
- }
184
- ```
185
- - The `/your_api/spec/swagger_helper.rb` (similar to rails_helper.rb file):
186
- ```ruby
187
- require 'rails_helper'
188
-
189
- Dir[::Rails.root.join("spec/swagger/**/schemas/*.rb")].each { |f| require f }
190
- Dir[::Rails.root.join("spec/swagger/**/definition.rb")].each { |f| require f }
191
-
192
- RSpec.configure do |config|
193
- # Specify a root folder where Swagger JSON files are generated
194
- # NOTE: If you're using the rswag-api to serve API descriptions, you'll need
195
- # to ensure that it's confiugred to serve Swagger from the same folder
196
- config.swagger_root = Rails.root.to_s + '/swagger'
197
-
198
- # Define one or more Swagger documents and provide global metadata for each one
199
- # When you run the 'rswag:specs:to_swagger' rake task, the complete Swagger will
200
- # be generated at the provided relative path under swagger_root
201
- # By default, the operations defined in spec files are added to the first
202
- # document below. You can override this behavior by adding a swagger_doc tag to the
203
- # the root example_group in your specs, e.g. describe '...', swagger_doc: 'v2/swagger.json'
204
- config.swagger_docs = {
205
- 'v1/swagger.json' => API_V1
206
- }
207
- end
208
- ```
209
- - An empty directory indicating where you should put your serializers for the first version: `/your_api/app/serializers/api/exposed/v1/.gitkeep`
210
- - An empty directory indicating where you should put your API tests: `/your_api/spec/integration/.gitkeep`
211
- - An empty directory indicating where you should put your swagger schemas `/your_api/spec/swagger/v1/schemas/.gitkeep`
212
-
213
155
  #### Command options:
214
156
 
215
157
  ##### `--authenticated-resources`
@@ -387,138 +329,17 @@ after doing this you will get:
387
329
  > With internal mode the file path will be: `/your_api/app/serializers/api/internal/blog_serializer.rb` and the class name: `Api::Internal::BlogSerializer`
388
330
 
389
331
  - A spec file under `/your_api/spec/integration/api/exposed/v1/blogs_spec.rb`
390
- - Exposed mode:
391
- ```ruby
392
- require 'swagger_helper'
393
-
394
- describe 'API V1 Blogs', swagger_doc: 'v1/swagger.json' do
395
- path '/blogs' do
396
- get 'Retrieves Blogs' do
397
- description 'Retrieves all the blogs'
398
- produces 'application/json'
399
-
400
- let(:collection_count) { 5 }
401
- let(:expected_collection_count) { collection_count }
402
-
403
- before { create_list(:blog, collection_count) }
404
-
405
- response '200', 'Blogs retrieved' do
406
- schema('$ref' => '#/definitions/blogs_collection')
407
-
408
- run_test! do |response|
409
- expect(JSON.parse(response.body)['blogs'].count).to eq(expected_collection_count)
410
- end
411
- end
412
- end
413
-
414
- post 'Creates Blog' do
415
- description 'Creates Blog'
416
- consumes 'application/json'
417
- produces 'application/json'
418
- parameter(name: :blog, in: :body)
419
-
420
- response '201', 'blog created' do
421
- let(:blog) do
422
- {
423
- title: 'Some title',
424
- body: 'Some body'
425
- }
426
- end
427
-
428
- run_test!
429
- end
430
-
431
- response '400', 'invalid attributes' do
432
- let(:blog) do
433
- {
434
- title: nil
435
- }
436
- end
437
-
438
- run_test!
439
- end
440
- end
441
- end
442
-
443
- path '/blogs/{id}' do
444
- parameter name: :id, in: :path, type: :integer
445
-
446
- let(:existent_blog) { create(:blog) }
447
- let(:id) { existent_blog.id }
448
-
449
- get 'Retrieves Blog' do
450
- produces 'application/json'
451
-
452
- response '200', 'blog retrieved' do
453
- schema('$ref' => '#/definitions/blog_resource')
454
-
455
- run_test!
456
- end
457
-
458
- response '404', 'invalid blog id' do
459
- let(:id) { 'invalid' }
460
- run_test!
461
- end
462
- end
463
-
464
- put 'Updates Blog' do
465
- description 'Updates Blog'
466
- consumes 'application/json'
467
- produces 'application/json'
468
- parameter(name: :blog, in: :body)
469
-
470
- response '200', 'blog updated' do
471
- let(:blog) do
472
- {
473
- title: 'Some title',
474
- body: 'Some body'
475
- }
476
- end
477
-
478
- run_test!
479
- end
480
-
481
- response '400', 'invalid attributes' do
482
- let(:blog) do
483
- {
484
- title: nil
485
- }
486
- end
487
-
488
- run_test!
489
- end
490
- end
491
-
492
- delete 'Deletes Blog' do
493
- produces 'application/json'
494
- description 'Deletes specific blog'
495
-
496
- response '204', 'blog deleted' do
497
- run_test!
498
- end
499
-
500
- response '404', 'blog not found' do
501
- let(:id) { 'invalid' }
502
-
503
- run_test!
504
- end
505
- end
506
- end
507
- end
508
-
509
- ```
510
- - Internal mode:
511
332
  ```ruby
512
333
  require 'rails_helper'
513
334
 
514
- describe 'Api::Internal::BlogsControllers', type: :request do
335
+ RSpec.describe 'Api::Exposed::V1::BlogsControllers', type: :request do
515
336
  describe 'GET /index' do
516
337
  let!(:blogs) { create_list(:blog, 5) }
517
338
  let(:collection) { JSON.parse(response.body)['blogs'] }
518
339
  let(:params) { {} }
519
340
 
520
341
  def perform
521
- get '/api/internal/blogs', params: params
342
+ get '/api/v1/blogs', params: params
522
343
  end
523
344
 
524
345
  before do
@@ -533,7 +354,8 @@ after doing this you will get:
533
354
  let(:params) do
534
355
  {
535
356
  blog: {
536
- title: 'Some title'
357
+ title: 'Some title',
358
+ body: 'Some body'
537
359
  }
538
360
  }
539
361
  end
@@ -543,7 +365,7 @@ after doing this you will get:
543
365
  end
544
366
 
545
367
  def perform
546
- post '/api/internal/blogs', params: params
368
+ post '/api/v1/blogs', params: params
547
369
  end
548
370
 
549
371
  before do
@@ -575,7 +397,7 @@ after doing this you will get:
575
397
  end
576
398
 
577
399
  def perform
578
- get '/api/internal/blogs/' + blog_id
400
+ get '/api/v1/blogs/' + blog_id
579
401
  end
580
402
 
581
403
  before do
@@ -598,7 +420,8 @@ after doing this you will get:
598
420
  let(:params) do
599
421
  {
600
422
  blog: {
601
- title: 'Some title'
423
+ title: 'Some title',
424
+ body: 'Some body'
602
425
  }
603
426
  }
604
427
  end
@@ -608,7 +431,7 @@ after doing this you will get:
608
431
  end
609
432
 
610
433
  def perform
611
- put '/api/internal/blogs/' + blog_id, params: params
434
+ put '/api/v1/blogs/' + blog_id, params: params
612
435
  end
613
436
 
614
437
  before do
@@ -642,14 +465,14 @@ after doing this you will get:
642
465
  let(:blog_id) { blog.id.to_s }
643
466
 
644
467
  def perform
645
- get '/api/internal/blogs/' + blog_id
468
+ delete '/api/v1/blogs/' + blog_id
646
469
  end
647
470
 
648
471
  before do
649
472
  perform
650
473
  end
651
474
 
652
- it { expect(response.status).to eq(200) }
475
+ it { expect(response.status).to eq(204) }
653
476
 
654
477
  context 'with resource not found' do
655
478
  let(:blog_id) { '666' }
@@ -658,66 +481,8 @@ after doing this you will get:
658
481
  end
659
482
  end
660
483
  end
661
-
662
- ```
663
- - A swagger schema definition under `/your_api/spec/swagger/v1/schemas/blog_schema.rb` (only for exposed mode)
664
- ```ruby
665
- BLOG_SCHEMA = {
666
- type: :object,
667
- properties: {
668
- id: { type: :integer, example: 666 },
669
- title: { type: :string, example: 'Some title' },
670
- body: { type: :string, example: 'Some body' },
671
- created_at: { type: :string, example: '1984-06-04 09:00', 'x-nullable': true },
672
- updated_at: { type: :string, example: '1984-06-04 09:00', 'x-nullable': true },
673
- portfolio_id: { type: :integer, example: 666, 'x-nullable': true }
674
- },
675
- required: [
676
- :title,
677
- :body
678
- ]
679
- }
680
-
681
- BLOGS_COLLECTION_SCHEMA = {
682
- type: "object",
683
- properties: {
684
- blogs: {
685
- type: "array",
686
- items: { "$ref" => "#/definitions/blog" }
687
- }
688
- },
689
- required: [
690
- :blogs
691
- ]
692
- }
693
-
694
- BLOG_RESOURCE_SCHEMA = {
695
- type: "object",
696
- properties: {
697
- blog: { "$ref" => "#/definitions/blog" }
698
- },
699
- required: [
700
- :blog
701
- ]
702
- }
703
484
  ```
704
- - An edited version of `your_api/api_example/spec/swagger/v1/definition.rb` with the schema definitions for the `Blog` resource. (only for exposed mode)
705
- ```ruby
706
- API_V1 = {
707
- swagger: '2.0',
708
- info: {
709
- title: 'API V1',
710
- version: 'v1'
711
- },
712
- basePath: '/api/v1',
713
- definitions: {
714
- blog: BLOG_SCHEMA,
715
- blogs_collection: BLOGS_COLLECTION_SCHEMA,
716
- blog_resource: BLOG_RESOURCE_SCHEMA,
717
- }
718
- }
719
- ```
720
-
485
+ > With internal mode the file path will be: `your_api/spec/integration/api/internal/blogs_spec.rb` and the class name: `Api::Internal::BlogsControllers`
721
486
  #### Command options (valid for internal and exposed modes):
722
487
 
723
488
  ##### `--attributes`
@@ -728,7 +493,7 @@ Use this option if you want to choose which attributes of your model to add to t
728
493
  rails g power_api:controller blog --attributes=title
729
494
  ```
730
495
 
731
- When you do this, you will see permited_params, serializers, swagger definitions, etc. showing only the selected attributes
496
+ When you do this, you will see permited_params, serializers, etc. showing only the selected attributes
732
497
 
733
498
  For example, the serializer under `/your_api/app/serializers/api/exposed/v1/blog_serializer.rb` will show:
734
499
  ```ruby
@@ -1022,38 +787,7 @@ Running the previous code we will get:
1022
787
  end
1023
788
  end
1024
789
  ```
1025
- - A spec file under `/your_api/spec/integration/api/v1/blogs_spec.rb` reflecting the nested resources:
1026
- ```ruby
1027
- require 'swagger_helper'
1028
-
1029
- describe 'API V1 Comments', swagger_doc: 'v1/swagger.json' do
1030
- let(:blog) { create(:blog) }
1031
- let(:blog_id) { blog.id }
1032
790
 
1033
- path '/blogs/{blog_id}/comments' do
1034
- parameter name: :blog_id, in: :path, type: :integer
1035
- get 'Retrieves Comments' do
1036
- description 'Retrieves all the comments'
1037
- produces 'application/json'
1038
-
1039
- let(:collection_count) { 5 }
1040
- let(:expected_collection_count) { collection_count }
1041
-
1042
- before { create_list(:comment, collection_count, blog: blog) }
1043
-
1044
- response '200', 'Comments retrieved' do
1045
- schema('$ref' => '#/definitions/comments_collection')
1046
-
1047
- run_test! do |response|
1048
- expect(JSON.parse(response.body)['data'].count).to eq(expected_collection_count)
1049
- end
1050
- end
1051
- end
1052
- end
1053
-
1054
- # more code...
1055
- end
1056
- ```
1057
791
  > Note that the options: `--parent-resource` and `--owned-by-authenticated-resource` cannot be used together.
1058
792
 
1059
793
  ## Inside the gem
@@ -95,41 +95,13 @@ class PowerApi::ControllerGenerator < Rails::Generators::NamedBase
95
95
  helper.format_ruby_file(helper.ams_serializer_path)
96
96
  end
97
97
 
98
- def configure_swagger
99
- return unless helper.versioned_api?
100
-
101
- create_swagger_schema
102
- add_swagger_schema_to_definition
103
- create_swagger_resource_spec
104
- end
105
-
106
98
  def add_rspec_tests
107
- return if helper.versioned_api?
108
-
109
99
  create_file(helper.resource_spec_path, helper.resource_spec_tpl)
110
100
  helper.format_ruby_file(helper.resource_spec_path)
111
101
  end
112
102
 
113
103
  private
114
104
 
115
- def create_swagger_schema
116
- create_file(helper.swagger_resource_schema_path, helper.swagger_schema_tpl)
117
- helper.format_ruby_file(helper.swagger_resource_schema_path)
118
- end
119
-
120
- def add_swagger_schema_to_definition
121
- insert_into_file(
122
- helper.swagger_version_definition_path,
123
- helper.swagger_definition_entry,
124
- after: helper.swagger_definition_line_to_inject_schema
125
- )
126
- end
127
-
128
- def create_swagger_resource_spec
129
- create_file(helper.swagger_resource_spec_path, helper.swagger_resource_spec_tpl)
130
- helper.format_ruby_file(helper.swagger_resource_spec_path)
131
- end
132
-
133
105
  def add_nested_route
134
106
  line_to_replace = helper.parent_resource_routes_line_regex
135
107
  nested_resource_line = helper.resource_route_tpl(
@@ -15,17 +15,6 @@ class PowerApi::ExposedApiConfigGenerator < Rails::Generators::Base
15
15
  )
16
16
  end
17
17
 
18
- def install_rswag
19
- generate "rswag:ui:install"
20
- generate "rswag:api:install"
21
- generate "rswag:specs:install"
22
-
23
- create_file(helper.rswag_ui_initializer_path, helper.rswag_ui_initializer_tpl, force: true)
24
- create_file(helper.swagger_helper_path, helper.swagger_helper_tpl, force: true)
25
- create_file(helper.spec_swagger_path)
26
- create_file(helper.spec_integration_path)
27
- end
28
-
29
18
  def install_first_version
30
19
  generate "power_api:version 1"
31
20
  end
@@ -23,29 +23,6 @@ class PowerApi::VersionGenerator < Rails::Generators::NamedBase
23
23
  create_file(helper.ams_serializers_path)
24
24
  end
25
25
 
26
- def add_swagger_related
27
- create_file(helper.swagger_schemas_path)
28
-
29
- create_file(
30
- helper.swagger_version_definition_path,
31
- helper.swagger_definition_tpl
32
- )
33
-
34
- insert_into_file(
35
- helper.rswag_ui_initializer_path,
36
- after: helper.rswag_ui_configure_line
37
- ) do
38
- helper.rswag_ui_swagger_endpoint
39
- end
40
-
41
- insert_into_file(
42
- helper.swagger_helper_path,
43
- after: helper.swagger_helper_api_definition_line
44
- ) do
45
- helper.swagger_helper_api_definition
46
- end
47
- end
48
-
49
26
  private
50
27
 
51
28
  def helper
@@ -15,7 +15,6 @@ module PowerApi
15
15
  require_relative "./generator_helper/active_record_resource"
16
16
  require_relative "./generator_helper/api_helper"
17
17
  require_relative "./generator_helper/resource_helper"
18
- require_relative "./generator_helper/swagger_helper"
19
18
  require_relative "./generator_helper/ams_helper"
20
19
  require_relative "./generator_helper/rspec_controller_helper"
21
20
  require_relative "./generator_helper/controller_helper"
@@ -27,10 +26,8 @@ module PowerApi
27
26
  require_relative "./generator_helpers"
28
27
  end
29
28
 
30
- initializer 'local_helper.action_controller' do
31
- ActiveSupport.on_load :action_controller do
32
- ApplicationController.helper PowerApi::ApplicationHelper
33
- end
29
+ initializer "power_api.view_helpers" do
30
+ ActiveSupport.on_load(:action_view) { include ::PowerApi::ApplicationHelper }
34
31
  end
35
32
  end
36
33
  end
@@ -131,7 +131,6 @@ module PowerApi::GeneratorHelper::ActiveRecordResource
131
131
  memo << {
132
132
  name: col_name,
133
133
  type: col.type,
134
- swagger_type: get_swagger_type(col.type),
135
134
  required: required_attribute?(col_name),
136
135
  example: get_attribute_example(col.type, col_name)
137
136
  }
@@ -145,19 +144,6 @@ module PowerApi::GeneratorHelper::ActiveRecordResource
145
144
  columns.select { |col| attrs.include?(col[:name]) }
146
145
  end
147
146
 
148
- def get_swagger_type(data_type)
149
- case data_type
150
- when :integer
151
- :integer
152
- when :float, :decimal
153
- :float
154
- when :boolean
155
- :boolean
156
- else
157
- :string
158
- end
159
- end
160
-
161
147
  def get_attribute_example(data_type, col_name)
162
148
  case data_type
163
149
  when :date
@@ -111,7 +111,7 @@ module PowerApi::GeneratorHelper::RspecControllerHelper
111
111
  spec_perform_tpl(http_verb: 'get', params: false, single_resource: true),
112
112
  with_authorized_resource_context,
113
113
  perform_block_tpl,
114
- "it { expect(response.status).to eq(200) }",
114
+ "it { expect(response.status).to eq(200) }\n",
115
115
  "context 'with resource not found' do",
116
116
  "let(:#{resource.snake_case}_id) { '666' }",
117
117
  "it { expect(response.status).to eq(404) }",
@@ -163,10 +163,10 @@ module PowerApi::GeneratorHelper::RspecControllerHelper
163
163
  "describe 'DELETE /destroy' do",
164
164
  spec_let_existent_resource_tpl,
165
165
  "let(:#{resource.snake_case}_id) { #{resource.snake_case}.id.to_s }\n",
166
- spec_perform_tpl(http_verb: 'get', params: false, single_resource: true),
166
+ spec_perform_tpl(http_verb: 'delete', params: false, single_resource: true),
167
167
  with_authorized_resource_context,
168
168
  perform_block_tpl,
169
- "it { expect(response.status).to eq(200) }",
169
+ "it { expect(response.status).to eq(204) }\n",
170
170
  "context 'with resource not found' do",
171
171
  "let(:#{resource.snake_case}_id) { '666' }",
172
172
  "it { expect(response.status).to eq(404) }",
@@ -189,7 +189,7 @@ module PowerApi::GeneratorHelper::RspecControllerHelper
189
189
  return if resource.required_resource_attributes.blank?
190
190
 
191
191
  concat_tpl_statements(
192
- "context 'with invalid attributes' do",
192
+ "\ncontext 'with invalid attributes' do",
193
193
  "let(:params) do",
194
194
  "{",
195
195
  "#{resource.snake_case}: {#{invalid_resource_params}}",
@@ -200,6 +200,22 @@ module PowerApi::GeneratorHelper::RspecControllerHelper
200
200
  )
201
201
  end
202
202
 
203
+ def invalid_resource_params
204
+ return unless resource.required_resource_attributes.any?
205
+
206
+ for_each_schema_attribute([resource.required_resource_attributes.first]) do |attr|
207
+ "#{attr[:name]}: nil,"
208
+ end
209
+ end
210
+
211
+ def for_each_schema_attribute(attributes)
212
+ attributes.inject("") do |memo, attr|
213
+ memo += "\n"
214
+ memo += yield(attr)
215
+ memo
216
+ end.delete_suffix(",")
217
+ end
218
+
203
219
  def with_authorized_resource_context
204
220
  if authenticated_resource?
205
221
  "context 'with authorized #{authenticated_resource.snake_case}' do"
@@ -3,7 +3,6 @@ module PowerApi
3
3
  include GeneratorHelper::ControllerActionsHelper
4
4
  include GeneratorHelper::ResourceHelper
5
5
  include GeneratorHelper::ApiHelper
6
- include GeneratorHelper::SwaggerHelper
7
6
  include GeneratorHelper::RspecControllerHelper
8
7
  include GeneratorHelper::AmsHelper
9
8
  include GeneratorHelper::ControllerHelper
@@ -1,3 +1,3 @@
1
1
  module PowerApi
2
- VERSION = '2.0.0'
2
+ VERSION = '2.1.0'
3
3
  end
data/lib/power_api.rb CHANGED
@@ -3,8 +3,6 @@ require "api-pagination"
3
3
  require "kaminari"
4
4
  require "ransack"
5
5
  require "responders"
6
- require "rswag/api"
7
- require "rswag/ui"
8
6
  require "simple_token_authentication"
9
7
  require "versionist"
10
8
 
data/power_api.gemspec CHANGED
@@ -26,8 +26,6 @@ Gem::Specification.new do |s|
26
26
  s.add_dependency "kaminari"
27
27
  s.add_dependency "ransack"
28
28
  s.add_dependency "responders"
29
- s.add_dependency "rswag-api"
30
- s.add_dependency "rswag-ui"
31
29
  s.add_dependency "simple_token_authentication", "~> 1.0"
32
30
  s.add_dependency "versionist", "~> 1.0"
33
31
 
@@ -38,7 +36,6 @@ Gem::Specification.new do |s|
38
36
  s.add_development_dependency "pry-rails"
39
37
  s.add_development_dependency "rspec-rails"
40
38
  s.add_development_dependency "rspec_junit_formatter"
41
- s.add_development_dependency "rswag-specs"
42
39
  s.add_development_dependency "rubocop", "0.65.0"
43
40
  s.add_development_dependency "rubocop-rspec"
44
41
  s.add_development_dependency "sqlite3", "~> 1.4.2"