power_api 1.0.0 → 2.0.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 +5 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +93 -90
- data/README.md +329 -75
- data/app/helpers/power_api/application_helper.rb +57 -0
- data/bin/clean_test_app +2 -0
- data/lib/generators/power_api/controller/controller_generator.rb +27 -15
- data/lib/generators/power_api/exposed_api_config/USAGE +5 -0
- data/lib/generators/power_api/exposed_api_config/exposed_api_config_generator.rb +58 -0
- data/lib/generators/power_api/install/install_generator.rb +2 -44
- data/lib/generators/power_api/internal_api_config/USAGE +5 -0
- data/lib/generators/power_api/internal_api_config/internal_api_config_generator.rb +31 -0
- data/lib/generators/power_api/version/version_generator.rb +2 -2
- data/lib/power_api/engine.rb +8 -1
- data/lib/power_api/errors.rb +2 -0
- data/lib/power_api/generator_helper/active_record_resource.rb +10 -6
- data/lib/power_api/generator_helper/ams_helper.rb +5 -11
- data/lib/power_api/generator_helper/api_helper.rb +61 -0
- data/lib/power_api/generator_helper/controller_helper.rb +45 -15
- data/lib/power_api/generator_helper/routes_helper.rb +22 -7
- data/lib/power_api/generator_helper/rspec_controller_helper.rb +306 -0
- data/lib/power_api/generator_helper/swagger_helper.rb +14 -24
- data/lib/power_api/generator_helpers.rb +2 -1
- data/lib/power_api/version.rb +1 -1
- data/spec/dummy/app/controllers/api/base_controller.rb +2 -0
- data/spec/dummy/app/controllers/api/internal/base_controller.rb +5 -0
- data/spec/dummy/app/controllers/api/internal/blogs_controller.rb +36 -0
- data/spec/dummy/app/serializers/api/internal/blog_serializer.rb +12 -0
- data/spec/dummy/config/initializers/active_model_serializers.rb +1 -0
- data/spec/dummy/config/initializers/api_pagination.rb +32 -0
- data/spec/dummy/config/routes.rb +2 -7
- data/spec/dummy/spec/helpers/power_api/application_helper_spec.rb +171 -0
- data/spec/dummy/spec/lib/power_api/generator_helper/ams_helper_spec.rb +50 -12
- data/spec/dummy/spec/lib/power_api/generator_helper/api_helper_spec.rb +115 -0
- data/spec/dummy/spec/lib/power_api/generator_helper/controller_helper_spec.rb +126 -34
- data/spec/dummy/spec/lib/power_api/generator_helper/routes_helper_spec.rb +29 -5
- data/spec/dummy/spec/lib/power_api/generator_helper/rspec_controller_helper_spec.rb +559 -0
- data/spec/dummy/spec/lib/power_api/generator_helper/swagger_helper_spec.rb +10 -20
- data/spec/dummy/spec/support/shared_examples/active_record_resource_atrributes.rb +22 -3
- metadata +27 -5
- data/lib/power_api/generator_helper/version_helper.rb +0 -16
- data/spec/dummy/spec/lib/power_api/generator_helper/version_helper_spec.rb +0 -55
data/README.md
CHANGED
@@ -26,11 +26,13 @@ These gems are:
|
|
26
26
|
- [Installation](#installation)
|
27
27
|
- [Usage](#usage)
|
28
28
|
- [Initial Setup](#initial-setup)
|
29
|
+
- [Exposed API mode](#exposed-api-mode)
|
29
30
|
- [Command options:](#command-options)
|
30
31
|
- [`--authenticated-resources`](#--authenticated-resources)
|
31
|
-
- [
|
32
|
-
- [
|
33
|
-
|
32
|
+
- [Internal API mode](#internal-api-mode)
|
33
|
+
- [Version Creation (exposed mode only)](#version-creation-exposed-mode-only)
|
34
|
+
- [Controller Generation (exposed and internal modes)](#controller-generation-exposed-and-internal-modes)
|
35
|
+
- [Command options (valid for internal and exposed modes):](#command-options-valid-for-internal-and-exposed-modes)
|
34
36
|
- [`--attributes`](#--attributes)
|
35
37
|
- [`--controller-actions`](#--controller-actions)
|
36
38
|
- [`--version-number`](#--version-number)
|
@@ -43,6 +45,7 @@ These gems are:
|
|
43
45
|
- [The `Api::Error` concern](#the-apierror-concern)
|
44
46
|
- [The `Api::Deprecated` concern](#the-apideprecated-concern)
|
45
47
|
- [The `ApiResponder`](#the-apiresponder)
|
48
|
+
- [The `PowerApi::ApplicationHelper#serialize_resource` helper method](#the-powerapiapplicationhelperserialize_resource-helper-method)
|
46
49
|
- [Testing](#testing)
|
47
50
|
- [Publishing](#publishing)
|
48
51
|
- [Contributing](#contributing)
|
@@ -88,30 +91,13 @@ After doing this you will get:
|
|
88
91
|
class Api::BaseController < PowerApi::BaseController
|
89
92
|
end
|
90
93
|
```
|
91
|
-
Here you should include everything common to all your
|
92
|
-
|
93
|
-
- A base controller for the first version of your API under `/your_api/app/controllers/api/v1/base_controller.rb`
|
94
|
-
```ruby
|
95
|
-
class Api::V1::BaseController < Api::BaseController
|
96
|
-
before_action do
|
97
|
-
self.namespace_for_serializer = ::Api::V1
|
98
|
-
end
|
99
|
-
end
|
100
|
-
```
|
101
|
-
Everything related to version 1 of your API must be included here.
|
94
|
+
Here you should include everything common to all your APIs. It is usually empty because most of the configuration comes in the `PowerApi::BaseController` that is inside the gem.
|
102
95
|
|
103
96
|
- Some initializers:
|
104
97
|
- `/your_api/config/initializers/active_model_serializers.rb`:
|
105
98
|
```ruby
|
106
|
-
|
107
|
-
def self.default_key_transform
|
108
|
-
:unaltered
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
ActiveModelSerializers.config.adapter = :json_api
|
99
|
+
ActiveModelSerializers.config.adapter = :json
|
113
100
|
```
|
114
|
-
Here we tell AMS that we will use the [json api](https://jsonapi.org/) format.
|
115
101
|
|
116
102
|
- `/your_api/config/initializers/api_pagination.rb`:
|
117
103
|
```ruby
|
@@ -123,6 +109,30 @@ After doing this you will get:
|
|
123
109
|
```
|
124
110
|
We use what comes by default and kaminari as pager.
|
125
111
|
|
112
|
+
After running the installer you must choose an API mode.
|
113
|
+
### Exposed API mode
|
114
|
+
|
115
|
+
Use this mode if your API will be accessed by multiple clients or if your API is served somewhere other than your client application.
|
116
|
+
|
117
|
+
You must run the following command to have the exposed API mode configuration:
|
118
|
+
|
119
|
+
```bash
|
120
|
+
rails generate power_api:exposed_api_config
|
121
|
+
```
|
122
|
+
|
123
|
+
After doing this you will get:
|
124
|
+
|
125
|
+
- A base controller for the first version of your API under `/your_api/app/controllers/api/exposed/v1/base_controller.rb`
|
126
|
+
```ruby
|
127
|
+
class Api::Exposed::V1::BaseController < Api::BaseController
|
128
|
+
before_action do
|
129
|
+
self.namespace_for_serializer = ::Api::V1
|
130
|
+
end
|
131
|
+
end
|
132
|
+
```
|
133
|
+
Everything related to version 1 of your API must be included here.
|
134
|
+
|
135
|
+
- Some initializers:
|
126
136
|
- `/your_api/config/initializers/rswag-api.rb`:
|
127
137
|
```ruby
|
128
138
|
Rswag::Api.configure do |c|
|
@@ -196,7 +206,7 @@ After doing this you will get:
|
|
196
206
|
}
|
197
207
|
end
|
198
208
|
```
|
199
|
-
- An empty directory indicating where you should put your serializers for the first version: `/your_api/app/serializers/api/v1/.gitkeep`
|
209
|
+
- An empty directory indicating where you should put your serializers for the first version: `/your_api/app/serializers/api/exposed/v1/.gitkeep`
|
200
210
|
- An empty directory indicating where you should put your API tests: `/your_api/spec/integration/.gitkeep`
|
201
211
|
- An empty directory indicating where you should put your swagger schemas `/your_api/spec/swagger/v1/schemas/.gitkeep`
|
202
212
|
|
@@ -225,7 +235,39 @@ Running the above code will generate, in addition to everything described in the
|
|
225
235
|
```
|
226
236
|
- The migration `/your_api/db/migrate/20200228173608_add_authentication_token_to_users.rb` to add the `authentication_token` to your users table.
|
227
237
|
|
228
|
-
###
|
238
|
+
### Internal API mode
|
239
|
+
|
240
|
+
Use this mode if your API and your client app will be served on the same place.
|
241
|
+
|
242
|
+
You must run the following command to have the internal API mode configuration:
|
243
|
+
|
244
|
+
```bash
|
245
|
+
rails generate power_api:internal_api_config
|
246
|
+
```
|
247
|
+
|
248
|
+
After doing this you will get:
|
249
|
+
|
250
|
+
- A base controller for your internal API under `/your_api/app/controllers/api/internal/base_controller.rb`
|
251
|
+
```ruby
|
252
|
+
class Api::Internal::BaseController < Api::BaseController
|
253
|
+
before_action do
|
254
|
+
self.namespace_for_serializer = ::Api::Internal
|
255
|
+
end
|
256
|
+
end
|
257
|
+
```
|
258
|
+
Anything shared by the internal API controllers should go here.
|
259
|
+
|
260
|
+
- A modified `/your_api/config/routes.rb` file:
|
261
|
+
```ruby
|
262
|
+
namespace :api, defaults: { format: :json } do
|
263
|
+
namespace :internal do
|
264
|
+
end
|
265
|
+
end
|
266
|
+
```
|
267
|
+
|
268
|
+
- An empty directory indicating where you should put your serializers: `/your_api/app/serializers/api/internal/.gitkeep`
|
269
|
+
|
270
|
+
### Version Creation (exposed mode only)
|
229
271
|
|
230
272
|
To add a new version you must run the following command:
|
231
273
|
```bash
|
@@ -238,7 +280,7 @@ rails g power_api:version 2
|
|
238
280
|
|
239
281
|
Doing this will add the same thing that was added for version one in the initial setup but this time for the number version provided as parameter.
|
240
282
|
|
241
|
-
### Controller Generation
|
283
|
+
### Controller Generation (exposed and internal modes)
|
242
284
|
|
243
285
|
To add a controller you must run the following command:
|
244
286
|
```bash
|
@@ -268,18 +310,29 @@ end
|
|
268
310
|
after doing this you will get:
|
269
311
|
|
270
312
|
- A modified `/your_api/config/routes.rb` file with the new resource:
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
313
|
+
- Exposed mode:
|
314
|
+
```ruby
|
315
|
+
Rails.application.routes.draw do
|
316
|
+
scope path: '/api' do
|
317
|
+
api_version(module: 'Api::V1', path: { value: 'v1' }, defaults: { format: 'json' }) do
|
318
|
+
resources :blogs
|
319
|
+
end
|
276
320
|
end
|
277
321
|
end
|
278
|
-
|
279
|
-
|
280
|
-
|
322
|
+
```
|
323
|
+
- Internal mode:
|
324
|
+
```ruby
|
325
|
+
Rails.application.routes.draw do
|
326
|
+
namespace :api, defaults: { format: :json } do
|
327
|
+
namespace :internal do
|
328
|
+
resources :blogs
|
329
|
+
end
|
330
|
+
end
|
331
|
+
end
|
332
|
+
```
|
333
|
+
- A controller under `/your_api/app/controllers/api/exposed/v1/blogs_controller.rb`
|
281
334
|
```ruby
|
282
|
-
class Api::V1::BlogsController < Api::V1::BaseController
|
335
|
+
class Api::Exposed::V1::BlogsController < Api::Exposed::V1::BaseController
|
283
336
|
def index
|
284
337
|
respond_with Blog.all
|
285
338
|
end
|
@@ -308,18 +361,22 @@ after doing this you will get:
|
|
308
361
|
|
309
362
|
def blog_params
|
310
363
|
params.require(:blog).permit(
|
364
|
+
:id,
|
311
365
|
:title,
|
312
366
|
:body,
|
313
367
|
)
|
314
368
|
end
|
315
369
|
end
|
316
370
|
```
|
317
|
-
|
371
|
+
> With internal mode the file path will be: `/your_api/app/controllers/api/internal/blogs_controller.rb` and the class name: `Api::Internal::BlogsController`
|
372
|
+
|
373
|
+
- A serializer under `/your_api/app/serializers/api/exposed/v1/blog_serializer.rb`
|
318
374
|
```ruby
|
319
|
-
class Api::V1::BlogSerializer < ActiveModel::Serializer
|
375
|
+
class Api::Exposed::V1::BlogSerializer < ActiveModel::Serializer
|
320
376
|
type :blog
|
321
377
|
|
322
378
|
attributes(
|
379
|
+
:id,
|
323
380
|
:title,
|
324
381
|
:body,
|
325
382
|
:created_at,
|
@@ -327,7 +384,10 @@ after doing this you will get:
|
|
327
384
|
)
|
328
385
|
end
|
329
386
|
```
|
330
|
-
|
387
|
+
> 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
|
+
|
389
|
+
- A spec file under `/your_api/spec/integration/api/exposed/v1/blogs_spec.rb`
|
390
|
+
- Exposed mode:
|
331
391
|
```ruby
|
332
392
|
require 'swagger_helper'
|
333
393
|
|
@@ -346,7 +406,7 @@ after doing this you will get:
|
|
346
406
|
schema('$ref' => '#/definitions/blogs_collection')
|
347
407
|
|
348
408
|
run_test! do |response|
|
349
|
-
expect(JSON.parse(response.body)['
|
409
|
+
expect(JSON.parse(response.body)['blogs'].count).to eq(expected_collection_count)
|
350
410
|
end
|
351
411
|
end
|
352
412
|
end
|
@@ -357,7 +417,7 @@ after doing this you will get:
|
|
357
417
|
produces 'application/json'
|
358
418
|
parameter(name: :blog, in: :body)
|
359
419
|
|
360
|
-
response '201', 'blog
|
420
|
+
response '201', 'blog created' do
|
361
421
|
let(:blog) do
|
362
422
|
{
|
363
423
|
title: 'Some title',
|
@@ -367,6 +427,16 @@ after doing this you will get:
|
|
367
427
|
|
368
428
|
run_test!
|
369
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
|
370
440
|
end
|
371
441
|
end
|
372
442
|
|
@@ -407,6 +477,16 @@ after doing this you will get:
|
|
407
477
|
|
408
478
|
run_test!
|
409
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
|
410
490
|
end
|
411
491
|
|
412
492
|
delete 'Deletes Blog' do
|
@@ -425,57 +505,203 @@ after doing this you will get:
|
|
425
505
|
end
|
426
506
|
end
|
427
507
|
end
|
508
|
+
|
428
509
|
```
|
429
|
-
-
|
510
|
+
- Internal mode:
|
511
|
+
```ruby
|
512
|
+
require 'rails_helper'
|
513
|
+
|
514
|
+
describe 'Api::Internal::BlogsControllers', type: :request do
|
515
|
+
describe 'GET /index' do
|
516
|
+
let!(:blogs) { create_list(:blog, 5) }
|
517
|
+
let(:collection) { JSON.parse(response.body)['blogs'] }
|
518
|
+
let(:params) { {} }
|
519
|
+
|
520
|
+
def perform
|
521
|
+
get '/api/internal/blogs', params: params
|
522
|
+
end
|
523
|
+
|
524
|
+
before do
|
525
|
+
perform
|
526
|
+
end
|
527
|
+
|
528
|
+
it { expect(collection.count).to eq(5) }
|
529
|
+
it { expect(response.status).to eq(200) }
|
530
|
+
end
|
531
|
+
|
532
|
+
describe 'POST /create' do
|
533
|
+
let(:params) do
|
534
|
+
{
|
535
|
+
blog: {
|
536
|
+
title: 'Some title'
|
537
|
+
}
|
538
|
+
}
|
539
|
+
end
|
540
|
+
|
541
|
+
let(:attributes) do
|
542
|
+
JSON.parse(response.body)['blog'].symbolize_keys
|
543
|
+
end
|
544
|
+
|
545
|
+
def perform
|
546
|
+
post '/api/internal/blogs', params: params
|
547
|
+
end
|
548
|
+
|
549
|
+
before do
|
550
|
+
perform
|
551
|
+
end
|
552
|
+
|
553
|
+
it { expect(attributes).to include(params[:blog]) }
|
554
|
+
it { expect(response.status).to eq(201) }
|
555
|
+
|
556
|
+
context 'with invalid attributes' do
|
557
|
+
let(:params) do
|
558
|
+
{
|
559
|
+
blog: {
|
560
|
+
title: nil
|
561
|
+
}
|
562
|
+
}
|
563
|
+
end
|
564
|
+
|
565
|
+
it { expect(response.status).to eq(400) }
|
566
|
+
end
|
567
|
+
end
|
568
|
+
|
569
|
+
describe 'GET /show' do
|
570
|
+
let(:blog) { create(:blog) }
|
571
|
+
let(:blog_id) { blog.id.to_s }
|
572
|
+
|
573
|
+
let(:attributes) do
|
574
|
+
JSON.parse(response.body)['blog'].symbolize_keys
|
575
|
+
end
|
576
|
+
|
577
|
+
def perform
|
578
|
+
get '/api/internal/blogs/' + blog_id
|
579
|
+
end
|
580
|
+
|
581
|
+
before do
|
582
|
+
perform
|
583
|
+
end
|
584
|
+
|
585
|
+
it { expect(response.status).to eq(200) }
|
586
|
+
|
587
|
+
context 'with resource not found' do
|
588
|
+
let(:blog_id) { '666' }
|
589
|
+
|
590
|
+
it { expect(response.status).to eq(404) }
|
591
|
+
end
|
592
|
+
end
|
593
|
+
|
594
|
+
describe 'PUT /update' do
|
595
|
+
let(:blog) { create(:blog) }
|
596
|
+
let(:blog_id) { blog.id.to_s }
|
597
|
+
|
598
|
+
let(:params) do
|
599
|
+
{
|
600
|
+
blog: {
|
601
|
+
title: 'Some title'
|
602
|
+
}
|
603
|
+
}
|
604
|
+
end
|
605
|
+
|
606
|
+
let(:attributes) do
|
607
|
+
JSON.parse(response.body)['blog'].symbolize_keys
|
608
|
+
end
|
609
|
+
|
610
|
+
def perform
|
611
|
+
put '/api/internal/blogs/' + blog_id, params: params
|
612
|
+
end
|
613
|
+
|
614
|
+
before do
|
615
|
+
perform
|
616
|
+
end
|
617
|
+
|
618
|
+
it { expect(attributes).to include(params[:blog]) }
|
619
|
+
it { expect(response.status).to eq(200) }
|
620
|
+
|
621
|
+
context 'with invalid attributes' do
|
622
|
+
let(:params) do
|
623
|
+
{
|
624
|
+
blog: {
|
625
|
+
title: nil
|
626
|
+
}
|
627
|
+
}
|
628
|
+
end
|
629
|
+
|
630
|
+
it { expect(response.status).to eq(400) }
|
631
|
+
end
|
632
|
+
|
633
|
+
context 'with resource not found' do
|
634
|
+
let(:blog_id) { '666' }
|
635
|
+
|
636
|
+
it { expect(response.status).to eq(404) }
|
637
|
+
end
|
638
|
+
end
|
639
|
+
|
640
|
+
describe 'DELETE /destroy' do
|
641
|
+
let(:blog) { create(:blog) }
|
642
|
+
let(:blog_id) { blog.id.to_s }
|
643
|
+
|
644
|
+
def perform
|
645
|
+
get '/api/internal/blogs/' + blog_id
|
646
|
+
end
|
647
|
+
|
648
|
+
before do
|
649
|
+
perform
|
650
|
+
end
|
651
|
+
|
652
|
+
it { expect(response.status).to eq(200) }
|
653
|
+
|
654
|
+
context 'with resource not found' do
|
655
|
+
let(:blog_id) { '666' }
|
656
|
+
|
657
|
+
it { expect(response.status).to eq(404) }
|
658
|
+
end
|
659
|
+
end
|
660
|
+
end
|
661
|
+
|
662
|
+
```
|
663
|
+
- A swagger schema definition under `/your_api/spec/swagger/v1/schemas/blog_schema.rb` (only for exposed mode)
|
430
664
|
```ruby
|
431
665
|
BLOG_SCHEMA = {
|
432
666
|
type: :object,
|
433
667
|
properties: {
|
434
|
-
id: { type: :
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
body: { type: :string, example: 'Some body', 'x-nullable': true },
|
441
|
-
created_at: { type: :string, example: '1984-06-04 09:00', 'x-nullable': true },
|
442
|
-
updated_at: { type: :string, example: '1984-06-04 09:00', 'x-nullable': true }
|
443
|
-
},
|
444
|
-
required: [
|
445
|
-
]
|
446
|
-
}
|
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 }
|
447
674
|
},
|
448
675
|
required: [
|
449
|
-
:
|
450
|
-
:
|
451
|
-
:attributes
|
676
|
+
:title,
|
677
|
+
:body
|
452
678
|
]
|
453
679
|
}
|
454
680
|
|
455
681
|
BLOGS_COLLECTION_SCHEMA = {
|
456
682
|
type: "object",
|
457
683
|
properties: {
|
458
|
-
|
684
|
+
blogs: {
|
459
685
|
type: "array",
|
460
686
|
items: { "$ref" => "#/definitions/blog" }
|
461
687
|
}
|
462
688
|
},
|
463
689
|
required: [
|
464
|
-
:
|
690
|
+
:blogs
|
465
691
|
]
|
466
692
|
}
|
467
693
|
|
468
694
|
BLOG_RESOURCE_SCHEMA = {
|
469
695
|
type: "object",
|
470
696
|
properties: {
|
471
|
-
|
697
|
+
blog: { "$ref" => "#/definitions/blog" }
|
472
698
|
},
|
473
699
|
required: [
|
474
|
-
:
|
700
|
+
:blog
|
475
701
|
]
|
476
702
|
}
|
477
703
|
```
|
478
|
-
- An edited version of `your_api/api_example/spec/swagger/v1/definition.rb` with the schema definitions for the `Blog` resource.
|
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)
|
479
705
|
```ruby
|
480
706
|
API_V1 = {
|
481
707
|
swagger: '2.0',
|
@@ -492,7 +718,7 @@ after doing this you will get:
|
|
492
718
|
}
|
493
719
|
```
|
494
720
|
|
495
|
-
#### Command options:
|
721
|
+
#### Command options (valid for internal and exposed modes):
|
496
722
|
|
497
723
|
##### `--attributes`
|
498
724
|
|
@@ -504,9 +730,9 @@ rails g power_api:controller blog --attributes=title
|
|
504
730
|
|
505
731
|
When you do this, you will see permited_params, serializers, swagger definitions, etc. showing only the selected attributes
|
506
732
|
|
507
|
-
For example, the serializer under `/your_api/app/serializers/api/v1/blog_serializer.rb` will show:
|
733
|
+
For example, the serializer under `/your_api/app/serializers/api/exposed/v1/blog_serializer.rb` will show:
|
508
734
|
```ruby
|
509
|
-
class Api::V1::BlogSerializer < ActiveModel::Serializer
|
735
|
+
class Api::Exposed::V1::BlogSerializer < ActiveModel::Serializer
|
510
736
|
type :blog
|
511
737
|
|
512
738
|
attributes(
|
@@ -528,7 +754,7 @@ When you do this, you will see that only relevant code is generated in controlle
|
|
528
754
|
For example, the controller would only include the `show` and `destroy` actions and wouldn't include the `blog_params` method:
|
529
755
|
|
530
756
|
```ruby
|
531
|
-
class Api::V1::
|
757
|
+
class Api::Exposed::V1::BlogController < Api::Exposed::V1::BaseController
|
532
758
|
def show
|
533
759
|
respond_with blog
|
534
760
|
end
|
@@ -553,6 +779,8 @@ Use this option if you want to decide which version the new controller will belo
|
|
553
779
|
rails g power_api:controller blog --version-number=2
|
554
780
|
```
|
555
781
|
|
782
|
+
> Important! When working with exposed api you should always specify the version, otherwise the controller will be generated for the internal api mode.
|
783
|
+
|
556
784
|
##### `--use-paginator`
|
557
785
|
|
558
786
|
Use this option if you want to paginate the index endpoint collection.
|
@@ -561,10 +789,10 @@ Use this option if you want to paginate the index endpoint collection.
|
|
561
789
|
rails g power_api:controller blog --use-paginator
|
562
790
|
```
|
563
791
|
|
564
|
-
The controller under `/your_api/app/controllers/api/v1/blogs_controller.rb` will be modified to use the paginator like this:
|
792
|
+
The controller under `/your_api/app/controllers/api/exposed/v1/blogs_controller.rb` will be modified to use the paginator like this:
|
565
793
|
|
566
794
|
```ruby
|
567
|
-
class Api::V1::BlogsController < Api::V1::BaseController
|
795
|
+
class Api::Exposed::V1::BlogsController < Api::Exposed::V1::BaseController
|
568
796
|
def index
|
569
797
|
respond_with paginate(Blog.all)
|
570
798
|
end
|
@@ -585,10 +813,10 @@ Use this option if you want to filter your index endpoint collection with [Ransa
|
|
585
813
|
rails g power_api:controller blog --allow-filters
|
586
814
|
```
|
587
815
|
|
588
|
-
The controller under `/your_api/app/controllers/api/v1/blogs_controller.rb` will be modified like this:
|
816
|
+
The controller under `/your_api/app/controllers/api/exposed/v1/blogs_controller.rb` will be modified like this:
|
589
817
|
|
590
818
|
```ruby
|
591
|
-
class Api::V1::BlogsController < Api::V1::BaseController
|
819
|
+
class Api::Exposed::V1::BlogsController < Api::Exposed::V1::BaseController
|
592
820
|
def index
|
593
821
|
respond_with filtered_collection(Blog.all)
|
594
822
|
end
|
@@ -625,13 +853,15 @@ rails g power_api:controller blog --authenticate-with=user
|
|
625
853
|
When you do this your controller will have the following line:
|
626
854
|
|
627
855
|
```ruby
|
628
|
-
class Api::V1::BlogsController < Api::V1::BaseController
|
856
|
+
class Api::Exposed::V1::BlogsController < Api::Exposed::V1::BaseController
|
629
857
|
acts_as_token_authentication_handler_for User, fallback: :exception
|
630
858
|
|
631
859
|
# mode code...
|
632
860
|
end
|
633
861
|
```
|
634
862
|
|
863
|
+
> With internal mode a `before_action :authenticate_user!` statement will be added instead of `acts_as_token_authentication_handler_for` in order to work with devise gem directly.
|
864
|
+
|
635
865
|
In addition, the specs under `/your_api/spec/integration/api/v1/blogs_spec.rb` will add tests related with authorization.
|
636
866
|
|
637
867
|
```ruby
|
@@ -653,7 +883,7 @@ rails g power_api:controller blog --authenticate-with=user --owned-by-authentica
|
|
653
883
|
The controller will look like this:
|
654
884
|
|
655
885
|
```ruby
|
656
|
-
class Api::V1::BlogsController < Api::V1::BaseController
|
886
|
+
class Api::Exposed::V1::BlogsController < Api::Exposed::V1::BaseController
|
657
887
|
acts_as_token_authentication_handler_for User, fallback: :exception
|
658
888
|
|
659
889
|
def index
|
@@ -688,6 +918,7 @@ class Api::V1::BlogsController < Api::V1::BaseController
|
|
688
918
|
|
689
919
|
def blog_params
|
690
920
|
params.require(:blog).permit(
|
921
|
+
:id,
|
691
922
|
:title,
|
692
923
|
:body
|
693
924
|
)
|
@@ -731,9 +962,9 @@ rails g power_api:controller comment --attributes=body --parent-resource=blog
|
|
731
962
|
|
732
963
|
Running the previous code we will get:
|
733
964
|
|
734
|
-
- The controller under `/your_api/app/controllers/api/v1/comments_controller.rb`:
|
965
|
+
- The controller under `/your_api/app/controllers/api/exposed/v1/comments_controller.rb`:
|
735
966
|
```ruby
|
736
|
-
class Api::V1::CommentsController < Api::V1::BaseController
|
967
|
+
class Api::Exposed::V1::CommentsController < Api::Exposed::V1::BaseController
|
737
968
|
def index
|
738
969
|
respond_with comments
|
739
970
|
end
|
@@ -770,6 +1001,7 @@ Running the previous code we will get:
|
|
770
1001
|
|
771
1002
|
def comment_params
|
772
1003
|
params.require(:comment).permit(
|
1004
|
+
:id,
|
773
1005
|
:body
|
774
1006
|
)
|
775
1007
|
end
|
@@ -868,7 +1100,7 @@ This module is useful when you want to mark endpoints as deprecated.
|
|
868
1100
|
For example, if you have the following controller:
|
869
1101
|
|
870
1102
|
```ruby
|
871
|
-
class Api::V1::CommentsController < Api::V1::BaseController
|
1103
|
+
class Api::Exposed::V1::CommentsController < Api::Exposed::V1::BaseController
|
872
1104
|
deprecate :index
|
873
1105
|
|
874
1106
|
def index
|
@@ -905,6 +1137,28 @@ end
|
|
905
1137
|
|
906
1138
|
As you can see, this simple [Responder](https://github.com/heartcombo/responders) handles the API response based on the HTTP verbs.
|
907
1139
|
|
1140
|
+
### The `PowerApi::ApplicationHelper#serialize_resource` helper method
|
1141
|
+
|
1142
|
+
This helper method is useful if you want to serialize ActiveRecord resources to use in your views. For example, you can do:
|
1143
|
+
|
1144
|
+
```
|
1145
|
+
<pre>
|
1146
|
+
<%= serialize_resource(@resource, @options) %>
|
1147
|
+
</pre>
|
1148
|
+
```
|
1149
|
+
|
1150
|
+
To get:
|
1151
|
+
|
1152
|
+
```
|
1153
|
+
{"id":1,"title":"lean","body":"bla","createdAt":"2022-01-08T18:15:46.624Z","updatedAt":"2022-01-08T18:15:46.624Z","portfolioId":null}
|
1154
|
+
```
|
1155
|
+
|
1156
|
+
The `@resource` parameter must be an ActiveRecord instance (`ApplicationRecord`) or collection (`ActiveRecord_Relation`).
|
1157
|
+
|
1158
|
+
The `@options` parameter must be a `Hash` and can contain the options you commonly use with Active Model Serializer gem (`fields`, `transform_key`, etc.) and some others:
|
1159
|
+
- `include_root`: to get something like: `{"id":1,"title":"lean"}` or `{"blog": {"id":1,"title":"lean"}}`.
|
1160
|
+
- `output_format`: can be `:hash` or `:json`.
|
1161
|
+
|
908
1162
|
## Testing
|
909
1163
|
|
910
1164
|
To run the specs you need to execute, **in the root path of the gem**, the following command:
|
@@ -944,4 +1198,4 @@ Power API is maintained by [platanus](http://platan.us).
|
|
944
1198
|
|
945
1199
|
## License
|
946
1200
|
|
947
|
-
Power API is ©
|
1201
|
+
Power API is © 2022 platanus, spa. It is free software and may be redistributed under the terms specified in the LICENSE file.
|