power_api 2.0.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
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"