apipie-rails 0.3.6 → 0.5.17
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.travis.yml +23 -7
- data/CHANGELOG.md +147 -2
- data/Gemfile +1 -0
- data/Gemfile.rails41 +2 -0
- data/Gemfile.rails42 +10 -1
- data/Gemfile.rails50 +9 -0
- data/Gemfile.rails51 +9 -0
- data/Gemfile.rails60 +14 -0
- data/PROPOSAL_FOR_RESPONSE_DESCRIPTIONS.md +244 -0
- data/README.rst +570 -17
- data/apipie-rails.gemspec +3 -3
- data/app/controllers/apipie/apipies_controller.rb +48 -17
- data/app/views/apipie/apipies/_method_detail.erb +21 -0
- data/app/views/apipie/apipies/_params.html.erb +4 -2
- data/app/views/apipie/apipies/index.html.erb +5 -1
- data/app/views/apipie/apipies/resource.html.erb +3 -0
- data/app/views/layouts/apipie/apipie.html.erb +1 -1
- data/config/locales/en.yml +1 -0
- data/config/locales/fr.yml +31 -0
- data/config/locales/it.yml +31 -0
- data/config/locales/ja.yml +31 -0
- data/lib/apipie/apipie_module.rb +22 -4
- data/lib/apipie/application.rb +55 -28
- data/lib/apipie/configuration.rb +19 -3
- data/lib/apipie/core_ext/route.rb +9 -0
- data/lib/apipie/dsl_definition.rb +151 -10
- data/lib/apipie/error_description.rb +9 -2
- data/lib/apipie/errors.rb +34 -0
- data/lib/apipie/extractor/collector.rb +4 -0
- data/lib/apipie/extractor/recorder.rb +13 -12
- data/lib/apipie/extractor/writer.rb +83 -55
- data/lib/apipie/extractor.rb +10 -4
- data/lib/apipie/method_description.rb +51 -4
- data/lib/apipie/param_description.rb +56 -2
- data/lib/apipie/resource_description.rb +10 -3
- data/lib/apipie/response_description.rb +131 -0
- data/lib/apipie/response_description_adapter.rb +200 -0
- data/lib/apipie/routes_formatter.rb +1 -1
- data/lib/apipie/rspec/response_validation_helper.rb +194 -0
- data/lib/apipie/static_dispatcher.rb +3 -2
- data/lib/apipie/swagger_generator.rb +708 -0
- data/lib/apipie/tag_list_description.rb +11 -0
- data/lib/apipie/validator.rb +69 -8
- data/lib/apipie/version.rb +1 -1
- data/lib/apipie-rails.rb +7 -0
- data/lib/tasks/apipie.rake +103 -8
- data/spec/controllers/apipies_controller_spec.rb +52 -12
- data/spec/controllers/concerns_controller_spec.rb +2 -2
- data/spec/controllers/extended_controller_spec.rb +14 -0
- data/spec/controllers/memes_controller_spec.rb +10 -0
- data/spec/controllers/users_controller_spec.rb +115 -75
- data/spec/dummy/app/controllers/application_controller.rb +5 -1
- data/spec/dummy/app/controllers/concerns/extending_concern.rb +12 -0
- data/spec/dummy/app/controllers/concerns/sample_controller.rb +5 -5
- data/spec/dummy/app/controllers/extended_controller.rb +14 -0
- data/spec/dummy/app/controllers/pets_controller.rb +408 -0
- data/spec/dummy/app/controllers/pets_using_auto_views_controller.rb +73 -0
- data/spec/dummy/app/controllers/pets_using_self_describing_classes_controller.rb +95 -0
- data/spec/dummy/app/controllers/tagged_cats_controller.rb +32 -0
- data/spec/dummy/app/controllers/tagged_dogs_controller.rb +15 -0
- data/spec/dummy/app/controllers/twitter_example_controller.rb +5 -0
- data/spec/dummy/app/controllers/users_controller.rb +19 -11
- data/spec/dummy/components/test_engine/Gemfile +6 -0
- data/spec/dummy/components/test_engine/app/controllers/test_engine/application_controller.rb +4 -0
- data/spec/dummy/components/test_engine/app/controllers/test_engine/memes_controller.rb +37 -0
- data/spec/dummy/components/test_engine/config/routes.rb +3 -0
- data/spec/dummy/components/test_engine/db/.gitkeep +0 -0
- data/spec/dummy/components/test_engine/lib/test_engine.rb +7 -0
- data/spec/dummy/components/test_engine/test_engine.gemspec +11 -0
- data/spec/dummy/config/application.rb +5 -0
- data/spec/dummy/config/environments/development.rb +3 -0
- data/spec/dummy/config/environments/production.rb +3 -0
- data/spec/dummy/config/environments/test.rb +3 -0
- data/spec/dummy/config/initializers/apipie.rb +3 -1
- data/spec/dummy/config/routes.rb +24 -1
- data/spec/lib/extractor/writer_spec.rb +32 -4
- data/spec/lib/file_handler_spec.rb +18 -0
- data/spec/lib/method_description_spec.rb +34 -0
- data/spec/lib/swagger/openapi_2_0_schema.json +1607 -0
- data/spec/lib/swagger/rake_swagger_spec.rb +139 -0
- data/spec/lib/swagger/response_validation_spec.rb +104 -0
- data/spec/lib/swagger/swagger_dsl_spec.rb +658 -0
- data/spec/lib/validator_spec.rb +58 -0
- data/spec/lib/validators/array_validator_spec.rb +28 -8
- data/spec/spec_helper.rb +68 -0
- metadata +75 -23
- data/Gemfile +0 -7
- data/Gemfile.rails32 +0 -6
- data/Gemfile.rails40 +0 -5
- data/lib/apipie/client/generator.rb +0 -135
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 855ada05457368ea7521d46865242c73a15c33a33546d7b0dac1d2b90d779c70
|
4
|
+
data.tar.gz: 0cc30d4f4a38a476cab6ed92b6a4a00c45bd2036c8b35fb8373fbb215fb2ea80
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9b0ba79aee65ed21249fa35336166783697719fabc74831816513ea1d0b91162bde342b51fad08121ea38c27f5015bbf196ac524049dcbbc8635dd0a57f13cff
|
7
|
+
data.tar.gz: 0f9f593ee579dba0baf16175e8c9d916dd370eba6a5c37cee4df2a92dea1efe0ea936b2444597274dd327244063000bb3a9cff454413956cd98bd27c5652afc6
|
data/.travis.yml
CHANGED
@@ -1,12 +1,28 @@
|
|
1
1
|
language: ruby
|
2
2
|
sudo: false
|
3
|
+
before_install: >-
|
4
|
+
if ruby -v | grep 'ruby 2.2'; then
|
5
|
+
gem install bundler -v '~> 1.17'
|
6
|
+
fi
|
3
7
|
rvm:
|
4
|
-
-
|
5
|
-
- 2.
|
6
|
-
- 2.
|
7
|
-
- 2.
|
8
|
+
- 2.2.10
|
9
|
+
- 2.3.8
|
10
|
+
- 2.4.5
|
11
|
+
- 2.5.3
|
12
|
+
- 2.6.0
|
8
13
|
gemfile:
|
9
|
-
- Gemfile.rails32
|
10
|
-
- Gemfile.rails40
|
11
|
-
- Gemfile.rails41
|
12
14
|
- Gemfile.rails42
|
15
|
+
- Gemfile.rails51 # Min ruby 2.2.2
|
16
|
+
- Gemfile.rails60 # Min ruby 2.5.0
|
17
|
+
matrix:
|
18
|
+
exclude:
|
19
|
+
- rvm: 2.5.3
|
20
|
+
gemfile: Gemfile.rails42
|
21
|
+
- rvm: 2.6.0
|
22
|
+
gemfile: Gemfile.rails42
|
23
|
+
- rvm: 2.2.10
|
24
|
+
gemfile: Gemfile.rails60
|
25
|
+
- rvm: 2.3.8
|
26
|
+
gemfile: Gemfile.rails60
|
27
|
+
- rvm: 2.4.5
|
28
|
+
gemfile: Gemfile.rails60
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,152 @@
|
|
1
|
-
===========
|
2
1
|
Changelog
|
3
2
|
===========
|
4
3
|
|
4
|
+
[v0.5.17](https://github.com/Apipie/apipie-rails/tree/v0.5.17) (2020-01-20)
|
5
|
+
--------
|
6
|
+
|
7
|
+
[Full Changelog](https://github.com/Apipie/apipie-rails/compare/v0.5.16...v0.5.17)
|
8
|
+
|
9
|
+
- Allows update metadata for methods [\#667](https://github.com/Apipie/apipie-rails/pull/667) ([speckins](https://github.com/speckins))
|
10
|
+
|
11
|
+
[v0.5.16](https://github.com/Apipie/apipie-rails/tree/v0.5.16) (2019-05-22)
|
12
|
+
--------
|
13
|
+
|
14
|
+
[Full Changelog](https://github.com/Apipie/apipie-rails/compare/v0.5.15...v0.5.16)
|
15
|
+
|
16
|
+
- Load file directly instead of using Rails constant [\#665](https://github.com/Apipie/apipie-rails/pull/665) ([speckins](https://github.com/speckins))
|
17
|
+
|
18
|
+
[v0.5.15](https://github.com/Apipie/apipie-rails/tree/v0.5.15) (2019-01-03)
|
19
|
+
--------
|
20
|
+
[Full Changelog](https://github.com/Apipie/apipie-rails/compare/v0.5.14...v0.5.15)
|
21
|
+
|
22
|
+
|
23
|
+
- Fix authorization of resources [\#655](https://github.com/Apipie/apipie-rails/pull/655) ([NielsKSchjoedt](https://github.com/NielsKSchjoedt))
|
24
|
+
- Use configured value when swagger\_content\_type\_input argument is not passed [\#648](https://github.com/Apipie/apipie-rails/pull/648) ([nullnull](https://github.com/nullnull))
|
25
|
+
- Fix "ArgumentError: string contains null byte" on malformed stings [\#477](https://github.com/Apipie/apipie-rails/pull/477) ([avokhmin](https://github.com/avokhmin))
|
26
|
+
|
27
|
+
v0.5.14
|
28
|
+
-------
|
29
|
+
- HTML escape validator values [\#645](https://github.com/Apipie/apipie-rails/pull/645) ([ekohl](https://github.com/ekohl))
|
30
|
+
- Support for adding new params via `update\_api` [\#642](https://github.com/Apipie/apipie-rails/pull/642) ([iNecas](https://github.com/iNecas))
|
31
|
+
- Allow the "null" JSON string to be used as a parameter in Apipie spec examples \(`show\_in\_doc`\) [\#641](https://github.com/Apipie/apipie-rails/pull/641) ([enrique-guillen](https://github.com/enrique-guillen))
|
32
|
+
- Fix examples recording for specific cases [\#640](https://github.com/Apipie/apipie-rails/pull/640) ([Marri](https://github.com/Marri))
|
33
|
+
- Add description section to response [\#639](https://github.com/Apipie/apipie-rails/pull/639) ([X1ting](https://github.com/X1ting))
|
34
|
+
|
35
|
+
|
36
|
+
v0.5.13
|
37
|
+
-------
|
38
|
+
- Fix swagger generation if a controller's parent doesn't define a resource_description [\#637](https://github.com/Apipie/apipie-rails/pull/637) ([enrique-guillen](https://github.com/enrique-guillen))
|
39
|
+
|
40
|
+
v0.5.12
|
41
|
+
-------
|
42
|
+
- Fix returns displaying [\#635](https://github.com/Apipie/apipie-rails/pull/635) ([X1ting](https://github.com/X1ting))
|
43
|
+
|
44
|
+
v0.5.11
|
45
|
+
-------
|
46
|
+
|
47
|
+
- Adds swagger tags in swagger output [\#634](https://github.com/Apipie/apipie-rails/pull/634) ([enrique-guillen](https://github.com/enrique-guillen))
|
48
|
+
- Generate swagger with headers [\#630](https://github.com/Apipie/apipie-rails/pull/630) ([Uysim](https://github.com/Uysim))
|
49
|
+
- Fix examples not being generated for Rails < 5.0.0 [\#633](https://github.com/Apipie/apipie-rails/pull/633) ([RomanKapitonov](https://github.com/RomanKapitonov))
|
50
|
+
|
51
|
+
v0.5.10
|
52
|
+
------
|
53
|
+
|
54
|
+
- Support response validation [\#626](https://github.com/Apipie/apipie-rails/pull/626) ([COzero](https://github.com/COzero))
|
55
|
+
|
56
|
+
v0.5.9
|
57
|
+
------
|
58
|
+
|
59
|
+
- Support response validation [\#619](https://github.com/Apipie/apipie-rails/pull/619) ([abenari](https://github.com/abenari))
|
60
|
+
- Expect :number to have type 'numeric' [\#614](https://github.com/Apipie/apipie-rails/pull/614) ([akofink](https://github.com/akofink))
|
61
|
+
- New validator - DecimalValidator [\#431](https://github.com/Apipie/apipie-rails/pull/431) ([kiddrew](https://github.com/kiddrew))
|
62
|
+
|
63
|
+
|
64
|
+
v0.5.8
|
65
|
+
------
|
66
|
+
|
67
|
+
- Swagger json includes apipie's description as swagger's description [\#615](https://github.com/Apipie/apipie-rails/pull/615) ([gogotanaka](https://github.com/gogotanaka))
|
68
|
+
- Fix api! issue by using underscore when appending `controller` to the default controller string [\#613](https://github.com/Apipie/apipie-rails/pull/613) ([kevinmarx](https://github.com/kevinmarx))
|
69
|
+
- Possibility to compress examples [\#600](https://github.com/Apipie/apipie-rails/pull/600) ([Haniyya](https://github.com/Haniyya))
|
70
|
+
- Possibility to describe responses [\#588](https://github.com/Apipie/apipie-rails/pull/588) ([elasti-ron](https://github.com/elasti-ron))
|
71
|
+
|
72
|
+
v0.5.7
|
73
|
+
------
|
74
|
+
|
75
|
+
- Fix example recording with Rails 5 [\#607](https://github.com/Apipie/apipie-rails/pull/607) ([adamruzicka](https://github.com/adamruzicka))
|
76
|
+
- Use SHA1 instead of MD5 to enable using APIPIE at FIPS-enables systems [\#605](https://github.com/Apipie/apipie-rails/pull/605) ([iNecas](https://github.com/iNecas))
|
77
|
+
- Replaced String\#constantize with String\#safe\_constantize so apipie won't break on a missing constant [\#575](https://github.com/Apipie/apipie-rails/pull/575) ([Haniyya](https://github.com/Haniyya))
|
78
|
+
- Added Swagger generation [\#569](https://github.com/Apipie/apipie-rails/pull/569) ([elasti-ron](https://github.com/elasti-ron))
|
79
|
+
|
80
|
+
v0.5.6
|
81
|
+
------
|
82
|
+
|
83
|
+
- Prevent missing translation span in title [\#571](https://github.com/Apipie/apipie-rails/pull/571) ([mbacovsky](https://github.com/mbacovsky))
|
84
|
+
- Clean up old generator code for CLI [\#572](https://github.com/Apipie/apipie-rails/pull/572) ([voxik](https://github.com/voxik))
|
85
|
+
- Added french locale [\#568](https://github.com/Apipie/apipie-rails/pull/568) ([giglemad](https://github.com/giglemad))
|
86
|
+
|
87
|
+
v0.5.5
|
88
|
+
------
|
89
|
+
|
90
|
+
- prevent lang in url when config.translate is false [\#562](https://github.com/Apipie/apipie-rails/pull/562) ([markmoser](https://github.com/markmoser))
|
91
|
+
- Allow for resource-level deprecations [\#567](https://github.com/Apipie/apipie-rails/pull/567) ([cross-p6](https://github.com/cross-p6))
|
92
|
+
|
93
|
+
v0.5.4
|
94
|
+
------
|
95
|
+
|
96
|
+
- Constantize controller class before calling superclass [\#558](https://github.com/Apipie/apipie-rails/pull/558) ([ydkn](https://github.com/ydkn))
|
97
|
+
|
98
|
+
v0.5.3
|
99
|
+
------
|
100
|
+
|
101
|
+
- Fix reloading when extending the apidoc from concern [\#557](https://github.com/Apipie/apipie-rails/pull/557) ([iNecas](https://github.com/iNecas))
|
102
|
+
- Fix example recording when using send\_file [\#504](https://github.com/Apipie/apipie-rails/pull/504) ([tdeo](https://github.com/tdeo))
|
103
|
+
|
104
|
+
v0.5.2
|
105
|
+
------
|
106
|
+
|
107
|
+
- A way to extend an exiting API via concern [\#554](https://github.com/Apipie/apipie-rails/pull/554) ([iNecas](https://github.com/iNecas))
|
108
|
+
- Fallback to apipie views when application override isn't present [\#552](https://github.com/Apipie/apipie-rails/pull/552) ([tstrachota](https://github.com/tstrachota))
|
109
|
+
- Updated setting default locale for api documentation [\#543](https://github.com/Apipie/apipie-rails/pull/543) ([DmitryKK](https://github.com/DmitryKK))
|
110
|
+
|
111
|
+
v0.5.1
|
112
|
+
------
|
113
|
+
|
114
|
+
- Use AD::Reloader on Rails 4, app.reloader only on Rails 5+ [\#541](https://github.com/Apipie/apipie-rails/pull/541) ([domcleal](https://github.com/domcleal))
|
115
|
+
- Recognize Rack Symbols as Status Codes [\#468](https://github.com/Apipie/apipie-rails/pull/468)([alex-tan](https://github.com/alex-tan))
|
116
|
+
|
117
|
+
v0.5.0
|
118
|
+
------
|
119
|
+
|
120
|
+
- Fix Rails 5.1 deprecations [\#530](https://github.com/Apipie/apipie-rails/pull/530) ([@Onumis](https://github.com/Onumis) [@sedx](https://github.com/sedx))
|
121
|
+
- **This release is no longer compatible with Ruby 1.9.x**
|
122
|
+
- Do not mutate strings passed as config options, fixes \#461 [\#537](https://github.com/Apipie/apipie-rails/pull/537) ([samphilipd](https://github.com/samphilipd))
|
123
|
+
- Added recursion for documentation, fixed bug in examples with paperclip [\#531](https://github.com/Apipie/apipie-rails/pull/531) ([blddmnd](https://github.com/blddmnd))
|
124
|
+
- Added locales/ja.yml for Japanese [\#529](https://github.com/Apipie/apipie-rails/pull/529) ([kikuchi0808](https://github.com/kikuchi0808))
|
125
|
+
|
126
|
+
|
127
|
+
v0.4.0
|
128
|
+
------
|
129
|
+
|
130
|
+
- Rails 5 compatibility [\#527](https://github.com/Apipie/apipie-rails/pull/527) ([iNecas](https://github.com/iNecas)) [\#420](https://github.com/Apipie/apipie-rails/pull/420) ([buren](https://github.com/buren)) [\#473](https://github.com/Apipie/apipie-rails/pull/473)([domcleal](https://github.com/domcleal))
|
131
|
+
- **This release is no longer compatible with Rails 3.x**
|
132
|
+
- Include delete request parmeters in generated documentation [\#524](https://github.com/Apipie/apipie-rails/pull/524) ([johnnaegle](https://github.com/johnnaegle))
|
133
|
+
- Allow a blank, not just nil, base\_url. [\#521](https://github.com/Apipie/apipie-rails/pull/521) ([johnnaegle](https://github.com/johnnaegle))
|
134
|
+
- Adds allow\_blank option [\#508](https://github.com/Apipie/apipie-rails/pull/508) ([MrLeebo](https://github.com/MrLeebo))
|
135
|
+
- Boolean Validator uses \<code\> instead of ' [\#502](https://github.com/Apipie/apipie-rails/pull/502) ([berfarah](https://github.com/berfarah))
|
136
|
+
- Fix type validator message [\#501](https://github.com/Apipie/apipie-rails/pull/501) ([cindygu-itglue](https://github.com/cindygu-itglue))
|
137
|
+
- Add IT locale [\#496](https://github.com/Apipie/apipie-rails/pull/496) ([alepore](https://github.com/alepore))
|
138
|
+
- Fix small typo on dsl\_definition data init [\#494](https://github.com/Apipie/apipie-rails/pull/494) ([begault](https://github.com/begault))
|
139
|
+
- Localize app info message [\#491](https://github.com/Apipie/apipie-rails/pull/491) ([belousovAV](https://github.com/belousovAV))
|
140
|
+
- Fix travis build [\#489](https://github.com/Apipie/apipie-rails/pull/489) ([mtparet](https://github.com/mtparet))
|
141
|
+
- Handle blank data when parsing a example's response [\#453](https://github.com/Apipie/apipie-rails/pull/453) ([stbenjam](https://github.com/stbenjam))
|
142
|
+
- Allow layouts to be overridable. Fixes a regression introduced in \#425. [\#447](https://github.com/Apipie/apipie-rails/pull/447) ([nilsojes](https://github.com/nilsojes))
|
143
|
+
|
144
|
+
v0.3.7
|
145
|
+
------
|
146
|
+
|
147
|
+
- Handle blank data when parsing a example's response [\#453](https://github.com/Apipie/apipie-rails/pull/453) ([stbenjam](https://github.com/stbenjam))
|
148
|
+
- Allow layouts to be overridable. Fixes a regression introduced in \#425. [\#447](https://github.com/Apipie/apipie-rails/pull/447) ([nilseriksson](https://github.com/nilseriksson))
|
149
|
+
|
5
150
|
v0.3.6
|
6
151
|
------
|
7
152
|
|
@@ -70,7 +215,7 @@ v0.3.2
|
|
70
215
|
v0.3.1
|
71
216
|
------
|
72
217
|
|
73
|
-
* Support for ``api!`` keyword in concerns
|
218
|
+
* Support for ``api!`` keyword in concerns
|
74
219
|
[#322](https://github.com/Apipie/apipie-rails/pull/322) [@iNecas][]
|
75
220
|
* More explicit ordering of the static dispatcher middleware
|
76
221
|
[#315](https://github.com/Apipie/apipie-rails/pull/315) [@iNecas][]
|
data/Gemfile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
./Gemfile.rails50
|
data/Gemfile.rails41
CHANGED
data/Gemfile.rails42
CHANGED
@@ -2,4 +2,13 @@ source "https://rubygems.org"
|
|
2
2
|
|
3
3
|
gemspec
|
4
4
|
|
5
|
-
gem 'rails', '~> 4.2.5
|
5
|
+
gem 'rails', '~> 4.2.5'
|
6
|
+
gem 'mime-types', '~> 2.99.3'
|
7
|
+
gem 'sqlite3', '~> 1.3.6'
|
8
|
+
|
9
|
+
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.1.0')
|
10
|
+
gem 'nokogiri', '~> 1.6.8'
|
11
|
+
gem 'rdoc', '~> 4.2.2'
|
12
|
+
end
|
13
|
+
|
14
|
+
gem 'test_engine', path: 'spec/dummy/components/test_engine', group: :test
|
data/Gemfile.rails50
ADDED
data/Gemfile.rails51
ADDED
data/Gemfile.rails60
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
source "https://rubygems.org"
|
2
|
+
|
3
|
+
gemspec
|
4
|
+
|
5
|
+
gem 'rails', '~> 6.0.0.rc1'
|
6
|
+
gem 'mime-types', '~> 2.99.3'
|
7
|
+
gem 'rails-controller-testing'
|
8
|
+
gem 'rspec-rails', git: 'https://github.com/rspec/rspec-rails', branch: '4-0-dev'
|
9
|
+
gem 'rspec-core', git: 'https://github.com/rspec/rspec-core'
|
10
|
+
gem 'rspec-mocks', git: 'https://github.com/rspec/rspec-mocks'
|
11
|
+
gem 'rspec-support', git: 'https://github.com/rspec/rspec-support'
|
12
|
+
gem 'rspec-expectations', git: 'https://github.com/rspec/rspec-expectations'
|
13
|
+
|
14
|
+
gem 'test_engine', path: 'spec/dummy/components/test_engine', group: :test
|
@@ -0,0 +1,244 @@
|
|
1
|
+
# Proposal for supporting response descriptions in Apipie
|
2
|
+
|
3
|
+
## Rationale
|
4
|
+
|
5
|
+
Swagger allows API authors to describe the structure of objects returned by REST API calls.
|
6
|
+
Client authors and code generators can use such descriptions for various purposes, such as verification,
|
7
|
+
autocompletion, and so forth.
|
8
|
+
|
9
|
+
The current Apipie DSL allows API authors to indicate returned error codes (using the `error` keyword),
|
10
|
+
but does not support descriptions of returned data objects. As such, swagger files
|
11
|
+
generated from the DSL do not include those, and are somewhat limited in their value.
|
12
|
+
|
13
|
+
This document proposes a minimalistic approach to extending the Apipie DSL to allow description of response
|
14
|
+
objects, and including those descriptions in generated swagger files.
|
15
|
+
|
16
|
+
## Design Objectives
|
17
|
+
|
18
|
+
* Full backward compatibility with the existing DSL
|
19
|
+
* Minimal implementation effort
|
20
|
+
* Enough expressiveness to support common use cases
|
21
|
+
* Optional integration of the DSL with advanced JSON generators (such as Grape-Entity)
|
22
|
+
* Allowing developers to easily verify that actual responses match the response declarations
|
23
|
+
|
24
|
+
## Approach
|
25
|
+
|
26
|
+
#### Add a `returns` keyword to the DSL, based on the existing `error` keyword
|
27
|
+
|
28
|
+
Currently, returned error codes are indicated using the `error` keyword, for example:
|
29
|
+
```ruby
|
30
|
+
api :GET, "/users/:id", "Show user profile"
|
31
|
+
error :code => 401, :desc => "Unauthorized"
|
32
|
+
```
|
33
|
+
|
34
|
+
The proposed approach is to add a `returns` keyword, that has the following syntax:
|
35
|
+
```ruby
|
36
|
+
returns <type-identifier> [, :code => <number>] [, :desc => <response-description>]
|
37
|
+
```
|
38
|
+
|
39
|
+
For example:
|
40
|
+
```ruby
|
41
|
+
api :GET, "/users/:id", "Show user profile"
|
42
|
+
error :code => 401, :desc => "Unauthorized"
|
43
|
+
returns :SomeTypeIdentifier # :code is not specified, so it is assumed to be 200
|
44
|
+
```
|
45
|
+
|
46
|
+
|
47
|
+
#### Leverage `param_group` for response object description
|
48
|
+
|
49
|
+
Apipie currently has a mechanism for describing complex objects using the `param_group` keyword.
|
50
|
+
It seems reasonable to leverage this mechanism as the basis of the response object description mechanism,
|
51
|
+
so that the `<type-identifier>` in the `returns` keyword will be the name of a param_group.
|
52
|
+
|
53
|
+
For example:
|
54
|
+
```ruby
|
55
|
+
def_param_group :user do
|
56
|
+
param :user, Hash, :desc => "User info", :required => true, :action_aware => true do
|
57
|
+
param_group :credentials
|
58
|
+
param :membership, ["standard","premium"], :desc => "User membership", :allow_nil => false
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
api :GET, "/users/:id", "Get user record"
|
63
|
+
returns :user, "the requested record"
|
64
|
+
error :code => 404, :desc => "no user with the specified id"
|
65
|
+
```
|
66
|
+
|
67
|
+
Implementation of this DSL extension would involve - as part of the implementation of the `returns` keyword -
|
68
|
+
the generation of a Apipie::ParamDescription object that has a Hash validator pointing to the param_group block.
|
69
|
+
|
70
|
+
#### Extend action-aware functionality to include 'response-only' parameters
|
71
|
+
|
72
|
+
In CRUD operations, it is common for `param_group` input definitions to be very similar to the
|
73
|
+
output of the API, with the exception of a very small number of fields (such as the `:id` field
|
74
|
+
which usually appears in the response, but is not described in the `param_group` because it is passed as a
|
75
|
+
path parameter).
|
76
|
+
|
77
|
+
To allow reuse of the `param_group`, it would be useful to its definition to describe parameters that are not passed
|
78
|
+
in the request but are returned in the response. This would be implementing by extending the DSL to
|
79
|
+
support a `:only_in => :response` option on `param` definitions. Similarly, params could be defined to be
|
80
|
+
`:only_in => :request` to indicate that they will not be included in the response.
|
81
|
+
|
82
|
+
For example:
|
83
|
+
```ruby
|
84
|
+
# in the following group, the :id param is ignored in requests, but included in responses
|
85
|
+
def_param_group :user do
|
86
|
+
param :user, Hash, :desc => "User info", :required => true, :action_aware => true do
|
87
|
+
param :id, Integer, :only_in => :response
|
88
|
+
param :requested_id, Integer, :only_in => :request
|
89
|
+
param_group :credentials
|
90
|
+
param :membership, ["standard","premium"], :desc => "User membership", :allow_nil => false
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
api :GET, "/users/:id", "Get user record"
|
95
|
+
returns :user, :desc => "the requested record" # includes the :id field, because this is a response
|
96
|
+
error :code => 404, :desc => "no user with the specified id"
|
97
|
+
```
|
98
|
+
|
99
|
+
|
100
|
+
#### Support `:array_of => <param_group-name>` in the `returns` keyword
|
101
|
+
|
102
|
+
Very often, a REST API call returns an array of some previously-defined object
|
103
|
+
(the most common example an `index` operation that returns an array of the same entity returned by a `show` request),
|
104
|
+
and it would be tedious to have to define a separate `param_group` for each one.
|
105
|
+
|
106
|
+
For added convenience, the `returns` keyword will also support an `:array_of =>` construct
|
107
|
+
to specify that an API call returns an array of some object type.
|
108
|
+
|
109
|
+
For example:
|
110
|
+
```ruby
|
111
|
+
api :GET, "/users", "Get all user records"
|
112
|
+
returns :array_of => :user, :desc => "the requested user records"
|
113
|
+
|
114
|
+
api :GET, "/user/:id", "Get a single user record"
|
115
|
+
returns :user, :desc => "the requested user record"
|
116
|
+
```
|
117
|
+
|
118
|
+
#### Integration with advanced JSON generators using an [adapter](https://en.wikipedia.org/wiki/Adapter_pattern) to `param_group`
|
119
|
+
|
120
|
+
While it makes sense for the sake of simplicity to leverage the `param_group` construct to describe
|
121
|
+
returned objects, it is likely that many developers will prefer to unify the
|
122
|
+
description of the response with the actual generation of the JSON.
|
123
|
+
|
124
|
+
Some JSON-generation libraries, such as [Grape-Entity](https://github.com/ruby-grape/grape-entity),
|
125
|
+
provide a declarative interface for describing an object model, allowing both runtime
|
126
|
+
generation of the response, as well as the ability to traverse the description to auto-generate
|
127
|
+
documentation.
|
128
|
+
|
129
|
+
Such libraries could be integrated with Apipie using adapters that wrap the library-specific
|
130
|
+
object description and expose an API that includes a `params_ordered` method that behaves in a
|
131
|
+
similar manner to [`Apipie::HashValidator.params_ordered`](https://github.com/Apipie/apipie-rails/blob/cfb42198bc39b5b30d953ba5a8b523bafdb4f897/lib/apipie/validator.rb#L315).
|
132
|
+
Such an adapter would make it possible to pass an externally-defined entity to the `returns` keyword
|
133
|
+
as if it were a `param_group`.
|
134
|
+
|
135
|
+
Such adapters can be created easily by having a class respond to `#describe_own_properties`
|
136
|
+
with an array of property description objects. When such a class is specified as the
|
137
|
+
parameter to a `returns` declaration, Apipie would query the class for its properties
|
138
|
+
by calling `<Class>#describe_own_properties`.
|
139
|
+
|
140
|
+
For example:
|
141
|
+
```ruby
|
142
|
+
# here is a class that can describe itself to Apipie
|
143
|
+
class Animal
|
144
|
+
def self.describe_own_properties
|
145
|
+
[
|
146
|
+
Apipie::prop(:id, Integer, {:description => 'Name of pet', :required => false}),
|
147
|
+
Apipie::prop(:animal_type, 'string', {:description => 'Type of pet', :values => ["dog", "cat", "iguana", "kangaroo"]}),
|
148
|
+
Apipie::additional_properties(false)
|
149
|
+
]
|
150
|
+
end
|
151
|
+
|
152
|
+
attr_accessor :id
|
153
|
+
attr_accessor :animal_type
|
154
|
+
end
|
155
|
+
|
156
|
+
# Here is an API defined as returning Animal objects.
|
157
|
+
# Apipie creates an internal adapter by querying Animal#describe_own_properties
|
158
|
+
api :GET, "/animals", "Get all records"
|
159
|
+
returns :array_of => Animal, :desc => "the requested records"
|
160
|
+
```
|
161
|
+
|
162
|
+
The `#describe_own_properties` mechanism can also be used with reflection so that a
|
163
|
+
class would query its own properties and populate the response to `#describe_own_properties`
|
164
|
+
automatically. See [this gist](https://gist.github.com/elasti-ron/ac145b2c85547487ca33e5216a69f527)
|
165
|
+
for an example of how Grape::Entity classes can automatically describe itself to Apipie
|
166
|
+
|
167
|
+
#### Response validation
|
168
|
+
|
169
|
+
The swagger definitions created by Apipie can be used to auto-generate clients that access the
|
170
|
+
described APIs. Those clients will break if the responses returned from the API do not match
|
171
|
+
the declarations. As such, it is very important to include unit tests that validate the actual
|
172
|
+
responses against the swagger definitions.
|
173
|
+
|
174
|
+
The ~~proposed~~ implemented mechanism provides two ways to include such validations in RSpec unit tests:
|
175
|
+
manual (using an RSpec matcher) and automated (by injecting a test into the http operations 'get', 'post',
|
176
|
+
raising an error if there is no match).
|
177
|
+
|
178
|
+
Example of the manual mechanism:
|
179
|
+
|
180
|
+
```ruby
|
181
|
+
require 'apipie/rspec/response_validation_helper'
|
182
|
+
|
183
|
+
RSpec.describe MyController, :type => :controller, :show_in_doc => true do
|
184
|
+
|
185
|
+
describe "GET stuff with response validation" do
|
186
|
+
render_views # this makes sure the 'get' operation will actually
|
187
|
+
# return the rendered view even though this is a Controller spec
|
188
|
+
|
189
|
+
it "does something" do
|
190
|
+
response = get :index, {format: :json}
|
191
|
+
|
192
|
+
# the following expectation will fail if the returned object
|
193
|
+
# does not match the 'returns' declaration in the Controller,
|
194
|
+
# or if there is no 'returns' declaration for the returned
|
195
|
+
# HTTP status code
|
196
|
+
expect(response).to match_declared_responses
|
197
|
+
end
|
198
|
+
end
|
199
|
+
```
|
200
|
+
|
201
|
+
|
202
|
+
Example of the automated mechanism:
|
203
|
+
```ruby
|
204
|
+
require 'apipie/rspec/response_validation_helper'
|
205
|
+
|
206
|
+
RSpec.describe MyController, :type => :controller, :show_in_doc => true do
|
207
|
+
|
208
|
+
describe "GET stuff with response validation" do
|
209
|
+
render_views
|
210
|
+
auto_validate_rendered_views
|
211
|
+
|
212
|
+
it "does something" do
|
213
|
+
get :index, {format: :json}
|
214
|
+
end
|
215
|
+
it "does something else" do
|
216
|
+
get :another_index, {format: :json}
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
describe "GET stuff without response validation" do
|
221
|
+
it "does something" do
|
222
|
+
get :index, {format: :json}
|
223
|
+
end
|
224
|
+
it "does something else" do
|
225
|
+
get :another_index, {format: :json}
|
226
|
+
end
|
227
|
+
end
|
228
|
+
```
|
229
|
+
|
230
|
+
Explanation of the implementation approach:
|
231
|
+
|
232
|
+
The Apipie Swagger Generator is enhanced to allow extraction of the JSON schema of the response object
|
233
|
+
for any controller#action[http-status]. When validation is required, the validator receives the
|
234
|
+
actual response object (along with information about the controller, action and http status code),
|
235
|
+
queries the swagger generator to get the schema, and uses the json-schema validator (gem) to validate
|
236
|
+
one against the other.
|
237
|
+
|
238
|
+
Note that there is a slight complication here: while supported by JSON-shema, the Swagger 2.0
|
239
|
+
specification does not support a mechanism to declare that fields in the response could be null.
|
240
|
+
As such, for a response that contains `null` fields, if the exact same schema used in the swagger def
|
241
|
+
is passed to the json-schema validator, the validation fails. To work around this issue, when asked
|
242
|
+
to provide the schema for the purpose of response validation (i.e., not for inclusion in the swagger),
|
243
|
+
the Apipie Swagger Generator creates a slightly modified schema which declares null values to be valid.
|
244
|
+
|