apipie-rails 1.2.3 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/build.yml +5 -4
  3. data/.github/workflows/rubocop-challenger.yml +1 -3
  4. data/.github/workflows/rubocop.yml +1 -1
  5. data/.rubocop_todo.yml +22 -28
  6. data/CHANGELOG.md +22 -0
  7. data/Gemfile +2 -3
  8. data/README.md +2088 -0
  9. data/apipie-rails.gemspec +7 -1
  10. data/app/views/apipie/apipies/_method_detail.erb +2 -0
  11. data/app/views/apipie/apipies/_params.html.erb +1 -0
  12. data/app/views/apipie/apipies/_params_plain.html.erb +1 -0
  13. data/config/locales/en.yml +1 -0
  14. data/config/locales/ko.yml +1 -0
  15. data/lib/apipie/application.rb +1 -1
  16. data/lib/apipie/dsl_definition.rb +10 -11
  17. data/lib/apipie/errors.rb +1 -1
  18. data/lib/apipie/extractor/collector.rb +1 -1
  19. data/lib/apipie/extractor/recorder.rb +1 -1
  20. data/lib/apipie/extractor/writer.rb +2 -2
  21. data/lib/apipie/generator/swagger/config.rb +1 -1
  22. data/lib/apipie/generator/swagger/method_description/parameters_service.rb +1 -1
  23. data/lib/apipie/generator/swagger/method_description/response_service.rb +14 -1
  24. data/lib/apipie/generator/swagger/param_description/builder.rb +9 -0
  25. data/lib/apipie/generator/swagger/param_description/type.rb +15 -2
  26. data/lib/apipie/generator/swagger/resource_description_collection.rb +2 -2
  27. data/lib/apipie/param_description.rb +1 -1
  28. data/lib/apipie/response_description.rb +34 -9
  29. data/lib/apipie/response_description_adapter.rb +3 -3
  30. data/lib/apipie/routes_formatter.rb +1 -1
  31. data/lib/apipie/static_dispatcher.rb +7 -1
  32. data/lib/apipie/version.rb +1 -1
  33. data/lib/tasks/apipie.rake +3 -3
  34. data/rel-eng/gem_release.ipynb +5 -5
  35. data/spec/controllers/users_controller_spec.rb +1 -1
  36. data/spec/dummy/app/controllers/api/v2/empty_middle_controller.rb +1 -1
  37. data/spec/dummy/app/controllers/pets_controller.rb +2 -2
  38. data/spec/dummy/app/controllers/twitter_example_controller.rb +3 -3
  39. data/spec/lib/apipie/apipies_controller_spec.rb +1 -1
  40. data/spec/lib/apipie/extractor_spec.rb +1 -1
  41. data/spec/lib/apipie/file_handler_spec.rb +1 -1
  42. data/spec/lib/apipie/generator/swagger/method_description/response_schema_service_spec.rb +6 -6
  43. data/spec/lib/apipie/generator/swagger/method_description/response_service_spec.rb +62 -0
  44. data/spec/lib/apipie/generator/swagger/param_description/builder_spec.rb +14 -2
  45. data/spec/lib/apipie/generator/swagger/param_description/type_spec.rb +6 -1
  46. data/spec/lib/apipie/param_description_spec.rb +1 -1
  47. data/spec/lib/apipie/response_description/response_object_spec.rb +22 -0
  48. data/spec/lib/apipie/response_description_spec.rb +56 -0
  49. data/spec/lib/apipie/swagger_generator_spec.rb +2 -2
  50. data/spec/lib/swagger/rake_swagger_spec.rb +6 -1
  51. data/spec/lib/swagger/swagger_dsl_spec.rb +1 -1
  52. data/spec/spec_helper.rb +1 -1
  53. metadata +12 -6
  54. data/README.rst +0 -1965
data/README.rst DELETED
@@ -1,1965 +0,0 @@
1
- ========================
2
- API Documentation Tool
3
- ========================
4
-
5
- .. image:: https://github.com/Apipie/apipie-rails/actions/workflows/build.yml/badge.svg
6
- :target: https://github.com/Apipie/apipie-rails/actions/workflows/build.yml
7
- .. image:: https://codeclimate.com/github/Apipie/apipie-rails.svg
8
- :target: https://codeclimate.com/github/Apipie/apipie-rails
9
- .. image:: https://badges.gitter.im/Apipie/apipie-rails.svg
10
- :alt: Join the chat at https://gitter.im/Apipie/apipie-rails
11
- :target: https://gitter.im/Apipie/apipie-rails?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
12
- .. image:: https://img.shields.io/gem/v/apipie-rails.svg
13
- :alt: Latest release
14
- :target: https://rubygems.org/gems/apipie-rails
15
-
16
- Apipie-rails is a DSL and Rails engine for documenting your RESTful
17
- API. Instead of traditional use of ``#comments``, Apipie lets you
18
- describe the code, through the code. This brings advantages like:
19
-
20
- * No need to learn yet another syntax, you already know Ruby, right?
21
- * Possibility of reusing the docs for other purposes (such as validation)
22
- * Easier to extend and maintain (no string parsing involved)
23
- * Possibility of reusing other sources for documentation purposes (such as
24
- routes etc.)
25
-
26
- The documentation is available from within your app (by default under the
27
- ``/apipie`` path.) In development mode, you can see the changes as you
28
- go. It's markup language agnostic, and even provides an API for reusing
29
- the documentation data in JSON.
30
-
31
- Getting started
32
- ---------------
33
-
34
- The easiest way to get Apipie up and running with your app is:
35
-
36
- .. code:: sh
37
-
38
- echo "gem 'apipie-rails'" >> Gemfile
39
- bundle install
40
- rails g apipie:install
41
-
42
- Now you can start documenting your resources and actions (see
43
- `DSL Reference`_ for more info):
44
-
45
- .. code:: ruby
46
-
47
- api :GET, '/users/:id'
48
- param :id, :number, desc: 'id of the requested user'
49
- def show
50
- # ...
51
- end
52
-
53
-
54
- Run your application and see the result at
55
- ``http://localhost:3000/apipie``. For further processing, you can
56
- use ``http://localhost:3000/apipie.json``.
57
-
58
- For a more comprehensive getting started guide, see
59
- `this demo <https://github.com/Apipie/apipie-demo>`_, which includes
60
- features such as generating documentation from tests, recording examples etc.
61
-
62
- Screenshots
63
- -----------
64
-
65
- .. image:: https://github.com/Apipie/apipie-rails/blob/master/images/screenshot-1.png
66
- .. image:: https://github.com/Apipie/apipie-rails/blob/master/images/screenshot-2.png
67
-
68
- Authors
69
- -------
70
-
71
- `Pajk <https://github.com/Pajk>`_ and `iNecas <https://github.com/iNecas>`_
72
-
73
- Contributors
74
- ------------
75
-
76
- See `Contributors page <https://github.com/Apipie/apipie-rails/graphs/contributors>`_. Special thanks to all of them!
77
-
78
- License
79
- -------
80
-
81
- Apipie-rails is released under the `MIT License <https://opensource.org/licenses/MIT>`_
82
-
83
- ===============
84
- Documentation
85
- ===============
86
-
87
- .. contents:: `Table Of Contents`
88
- :depth: 2
89
-
90
- ===============
91
- DSL Reference
92
- ===============
93
-
94
- Resource Description
95
- --------------------
96
-
97
- You can describe a resource on the controller level. The description is introduced by calling
98
- ``resource_description do ... end``.
99
-
100
- Inheritance is supported, so you can specify common params for group of controllers in their parent
101
- class.
102
-
103
- The following keywords are available (all are optional):
104
-
105
- resource_id
106
- How the resource will be referenced in Apipie (paths, ``see`` command etc.); by default `controller_name.downcase` is used.
107
-
108
- name
109
- Human readable name of resource. By default ``class.name.humanize`` is used.
110
-
111
- - Can be specified as a proc, which will receive the controller class as an argument.
112
- - Can be a symbol, which will be sent to the controller class to get the name.
113
- - Can be a string, which will be used as is.
114
-
115
- short (also short_description)
116
- Short description of the resource (it's shown on both the list of resources, and resource details)
117
-
118
- desc (also description and full_description)
119
- Full description of the resource (shown only in resource details)
120
-
121
- param
122
- Common params for all methods defined in controller/child controllers.
123
-
124
- returns
125
- Common responses for all methods defined in controller/child controllers.
126
-
127
- api_base_url
128
- What URL is the resource available under.
129
-
130
- api_versions (also api_version)
131
- What versions does the controller define the resource. (See `Versioning`_ for details.)
132
-
133
- formats
134
- Request / response formats.
135
-
136
- error
137
- Describe every possible error that can happen when calling all
138
- methods defined in controller. HTTP response code and description can be provided.
139
-
140
- app_info
141
- In case of versioning, this sets app info description on a per_version basis.
142
-
143
- meta
144
- Hash or array with custom metadata.
145
-
146
- deprecated
147
- Boolean value indicating if the resource is marked as deprecated. (Default false)
148
-
149
- Example:
150
- ~~~~~~~~
151
-
152
- .. code:: ruby
153
-
154
- resource_description do
155
- short 'Site members'
156
- formats ['json']
157
- param :id, Integer, :desc => "User ID", :required => false
158
- param :resource_param, Hash, :desc => 'Param description for all methods' do
159
- param :ausername, String, :desc => "Username for login", :required => true
160
- param :apassword, String, :desc => "Password for login", :required => true
161
- end
162
- api_version "development"
163
- error 404, "Missing"
164
- error 500, "Server crashed for some <%= reason %>", :meta => {:anything => "you can think of"}
165
- error :unprocessable_entity, "Could not save the entity."
166
- returns :code => 403 do
167
- property :reason, String, :desc => "Why this was forbidden"
168
- end
169
- meta :author => {:name => 'John', :surname => 'Doe'}
170
- deprecated false
171
- description <<-EOS
172
- == Long description
173
- Example resource for rest api documentation
174
- These can now be accessed in <tt>shared/header</tt> with:
175
- Headline: <%= headline %>
176
- First name: <%= person.first_name %>
177
-
178
- If you need to find out whether a certain local variable has been
179
- assigned a value in a particular render call, you need to use the
180
- following pattern:
181
-
182
- <% if local_assigns.has_key? :headline %>
183
- Headline: <%= headline %>
184
- <% end %>
185
-
186
- Testing using <tt>defined? headline</tt> will not work. This is an
187
- implementation restriction.
188
-
189
- === Template caching
190
-
191
- By default, Rails will compile each template to a method in order
192
- to render it. When you alter a template, Rails will check the
193
- file's modification time and recompile it in development mode.
194
- EOS
195
- end
196
-
197
-
198
- Method Description
199
- ------------------
200
-
201
- Then describe methods available to your API.
202
-
203
- api
204
- Describe how this method is exposed, and provide a short description.
205
- The first parameter is HTTP method (one of :GET/:POST/:PUT/:DELETE).
206
- The second parameter is the relative URL path which is mapped to this
207
- method. The last parameter is the methods short description.
208
- You can use this +api+ method more than once per method. It could
209
- be useful when there are more routes mapped to it.
210
-
211
- When providing just one argument (description), or no argument at all,
212
- the paths will be loaded from the routes.rb file.
213
-
214
- api!
215
- Provide a short description and additional option.
216
- The last parameter is the methods short description.
217
- The paths will be loaded from routes.rb file. See
218
- `Rails Routes Integration`_ for more details.
219
-
220
- api_versions (also api_version)
221
- What version(s) does the action belong to. (See `Versioning`_ for details.)
222
-
223
- param
224
- Look at `Parameter description`_ section for details.
225
-
226
- returns
227
- Look at `Response description`_ section for details.
228
-
229
- tags
230
- Adds tags for grouping operations together in Swagger outputs. See `swagger`_
231
- for more details. You can also provide tags in the `Resource Description`_
232
- block so that they are automatically prepended to all action tags in the
233
- controller.
234
-
235
- formats
236
- Method level request / response formats.
237
-
238
- error
239
- Describe each possible error that can happen while calling this
240
- method. HTTP response code and description can be provided.
241
-
242
- description
243
- Full method description, which will be converted into HTML by the
244
- chosen markup language processor.
245
-
246
- example
247
- Provide an example of the server response; whole communication or response type.
248
- It will be formatted as code.
249
-
250
- see
251
- Provide reference to another method, this has to be a string with
252
- controller_name#method_name.
253
-
254
- meta
255
- Hash or array with custom metadata.
256
-
257
- show
258
- Resource is hidden from documentation when set to false (true by default)
259
-
260
- Example:
261
- ~~~~~~~~
262
-
263
- .. code:: ruby
264
-
265
- # The simplest case: just load the paths from routes.rb
266
- api!
267
- def index
268
- end
269
-
270
- # More complex example
271
- api :GET, "/users/:id", "Show user profile"
272
- show false
273
- error :code => 401, :desc => "Unauthorized"
274
- error :code => 404, :desc => "Not Found", :meta => {:anything => "you can think of"}
275
- param :session, String, :desc => "user is logged in", :required => true
276
- param :regexp_param, /^[0-9]* years/, :desc => "regexp param"
277
- param :array_param, [100, "one", "two", 1, 2], :desc => "array validator"
278
- param :boolean_param, [true, false], :desc => "array validator with boolean"
279
- param :proc_param, lambda { |val|
280
- val == "param value" ? true : "The only good value is 'param value'."
281
- }, :desc => "proc validator"
282
- param :param_with_metadata, String, :desc => "", :meta => [:your, :custom, :metadata]
283
- returns :code => 200, :desc => "a successful response" do
284
- property :value1, String, :desc => "A string value"
285
- property :value2, Integer, :desc => "An integer value"
286
- property :value3, Hash, :desc => "An object" do
287
- property :enum1, ['v1', 'v2'], :desc => "One of 2 possible string values"
288
- end
289
- end
290
- tags %w[profiles logins]
291
- tags 'more', 'related', 'resources'
292
- description "method description"
293
- formats ['json', 'jsonp', 'xml']
294
- meta :message => "Some very important info"
295
- example " 'user': {...} "
296
- see "users#showme", "link description"
297
- see :link => "users#update", :desc => "another link description"
298
- def show
299
- #...
300
- end
301
-
302
- Parameter Description
303
- ---------------------
304
-
305
- Use ``param`` to describe every possible parameter. You can use the Hash validator
306
- in conjunction with a block given to the param method to describe nested parameters.
307
-
308
- name
309
- The first argument is the parameter name as a symbol.
310
-
311
- validator
312
- Second parameter is the parameter validator, choose one from section `Validators`_
313
-
314
- desc
315
- Parameter description.
316
-
317
- required
318
- Set this true/false to make it required/optional. Default is optional
319
-
320
- allow_nil
321
- Setting this to true means that ``nil`` can be passed.
322
-
323
- allow_blank
324
- Like ``allow_nil``, but for blank values. ``false``, ``""``, ``' '``, ``nil``, ``[]``, and ``{}`` are all blank.
325
-
326
- as
327
- Used by the processing functionality to change the name of a key params.
328
-
329
- meta
330
- Hash or array with custom metadata.
331
-
332
- show
333
- Parameter is hidden from documentation when set to false (true by default)
334
-
335
- missing_message
336
- Specify the message to be returned if the parameter is missing as a string or Proc.
337
- Defaults to ``Missing parameter #{name}`` if not specified.
338
-
339
- only_in
340
- This can be set to ``:request`` or ``:response``.
341
- Setting to ``:response`` causes the param to be ignored when used as part of a request description.
342
- Setting to ``:request`` causes this param to be ignored when used as part of a response description.
343
- If ``only_in`` is not specified, the param definition is used for both requests and responses.
344
- (Note that the keyword ``property`` is similar to ``param``, but it has a ``:only_in => :response`` default).
345
-
346
- Example:
347
- ~~~~~~~~
348
-
349
- .. code:: ruby
350
-
351
- param :user, Hash, :desc => "User info" do
352
- param :username, String, :desc => "Username for login", :required => true
353
- param :password, String, :desc => "Password for login", :required => true
354
- param :membership, ["standard","premium"], :desc => "User membership"
355
- param :admin_override, String, :desc => "Not shown in documentation", :show => false
356
- param :ip_address, String, :desc => "IP address", :required => true, :missing_message => lambda { I18n.t("ip_address.required") }
357
- end
358
- def create
359
- #...
360
- end
361
-
362
- deprecated
363
- Indicates if the parameter is marked as deprecated.
364
-
365
- Example
366
- ~~~~~~~~
367
-
368
- .. code:: ruby
369
-
370
- param :pet_name, String, desc: "Name of pet", deprecated: true
371
- param :pet_name, String, desc: "Name of pet", deprecated: 'Some deprecation info'
372
- param :pet_name, String, desc: "Name of pet", deprecated: { in: "2.3", info: "Something", sunset: "3.0" }
373
- def create
374
- #...
375
- end
376
-
377
-
378
- DRY with param_group
379
- --------------------
380
-
381
- Often, params occur together in more actions. Typically, most of the
382
- params for ``create`` and ``update`` actions are shared between them.
383
-
384
- These params can be extracted with ``def_param_group`` and
385
- ``param_group`` keywords.
386
-
387
- The definition is looked up in the scope of the controller. If the
388
- group is defined in a different controller, it might be referenced by
389
- specifying the second argument.
390
-
391
- Example:
392
- ~~~~~~~~
393
-
394
- .. code:: ruby
395
-
396
- # v1/users_controller.rb
397
- def_param_group :address do
398
- param :street, String
399
- param :number, Integer
400
- param :zip, String
401
- end
402
-
403
- def_param_group :user do
404
- param :user, Hash do
405
- param :name, String, "Name of the user"
406
- param_group :address
407
- end
408
- end
409
-
410
- api :POST, "/users", "Create a user"
411
- param_group :user
412
- def create
413
- # ...
414
- end
415
-
416
- api :PUT, "/users/:id", "Update a user"
417
- param_group :user
418
- def update
419
- # ...
420
- end
421
-
422
- # v2/users_controller.rb
423
- api :POST, "/users", "Create a user"
424
- param_group :user, V1::UsersController
425
- def create
426
- # ...
427
- end
428
-
429
- Action Aware params
430
- -------------------
431
-
432
- In CRUD operations, this pattern occurs quite often - params that need
433
- to be set are:
434
-
435
- * for create action: ``required => true`` and ``allow_nil => false``
436
- * for update action: ``required => false`` and ``allow_nil => false``
437
-
438
- This makes it hard to share the param definitions across theses
439
- actions. Therefore, you can make the description a bit smarter by
440
- setting ``:action_aware => true``.
441
-
442
- You can specify explicitly how the param group should be evaluated
443
- with ``:as`` option (either :create or :update)
444
-
445
- Example
446
- ~~~~~~~
447
-
448
- .. code:: ruby
449
-
450
- def_param_group :user do
451
- param :user, Hash, :action_aware => true do
452
- param :name, String, :required => true
453
- param :description, String
454
- end
455
- end
456
-
457
- api :POST, "/users", "Create a user"
458
- param_group :user
459
- def create
460
- # ...
461
- end
462
-
463
- api :PUT, "/users/admin", "Create an admin"
464
- param_group :user, :as => :create
465
- def create_admin
466
- # ...
467
- end
468
-
469
- api :PUT, "/users/:id", "Update a user"
470
- param_group :user
471
- def update
472
- # ...
473
- end
474
-
475
- In this case, ``user[name]`` will be not be allowed nil for all
476
- actions and required only for ``create`` and ``create_admin``. Params
477
- with ``allow_nil`` set explicitly don't have this value changed.
478
-
479
- Action awareness is inherited from ancestors (in terms of
480
- nested params).
481
-
482
-
483
- Response Description
484
- --------------------
485
-
486
- The response from an API call can be documented by adding a ``returns`` statement to the method
487
- description. This is especially useful when using Apipie to auto-generate a machine-readable Swagger
488
- definition of your API (see the `swagger`_ section for more details).
489
-
490
- A ``returns`` statement has several possible formats:
491
-
492
- .. code:: ruby
493
-
494
- # format #1: reference to a param-group
495
- returns <param-group-name> [, :code => <number>|<http-response-code-symbol>] [, :desc => <human-readable description>]
496
-
497
- # format #2: inline response definition
498
- returns :code => <number>|<http-response-code-symbol> [, :desc => <human-readable description>] do
499
- # property ...
500
- # property ...
501
- # param_group ...
502
- end
503
-
504
- # format #3: describing an array-of-objects response
505
- returns :array_of => <param-group-name> [, :code => <number>|<http-response-code-symbol>] [, :desc => <human-readable description>]
506
-
507
-
508
- If the ``:code`` argument is ommitted, ``200`` is used.
509
-
510
-
511
- Example
512
- ~~~~~~~
513
-
514
- .. code:: ruby
515
-
516
- # ------------------------------------------------
517
- # Example of format #1 (reference to param-group):
518
- # ------------------------------------------------
519
- # the param_group :pet is defined here to describe the output returned by the method below.
520
- def_param_group :pet do
521
- property :pet_name, String, :desc => "Name of pet"
522
- property :animal_type, ['dog','cat','iguana','kangaroo'], :desc => "Type of pet"
523
- end
524
-
525
- api :GET, "/pets/:id", "Get a pet record"
526
- returns :pet, :desc => "The pet"
527
- def show_detailed
528
- render JSON({:pet_name => "Skippie", :animal_type => "kangaroo"})
529
- end
530
-
531
- # ------------------------------------------------
532
- # Example of format #2 (inline):
533
- # ------------------------------------------------
534
- api :GET, "/pets/:id/with-extra-details", "Get a detailed pet record"
535
- returns :code => 200, :desc => "Detailed info about the pet" do
536
- param_group :pet
537
- property :num_legs, Integer, :desc => "How many legs the pet has"
538
- end
539
- def show
540
- render JSON({:pet_name => "Barkie", :animal_type => "iguana", :legs => 4})
541
- end
542
-
543
- # ------------------------------------------------
544
- # Example of format #3 (array response):
545
- # ------------------------------------------------
546
- api :GET, "/pets", "Get all pet records"
547
- returns :array_of => :pet, :code => 200, :desc => "All pets"
548
- def index
549
- render JSON([ {:pet_name => "Skippie", :animal_type => "kangaroo"},
550
- {:pet_name => "Woofie", :animal_type => "cat"} ])
551
- end
552
-
553
-
554
- Note the use of the ``property`` keyword rather than ``param``. This is the
555
- preferred mechanism for documenting response-only fields.
556
-
557
-
558
- The Property keyword
559
- ::::::::::::::::::::::::::::::::::::::::::::::::
560
-
561
- ``property`` is very similar to ``param`` with the following differences:
562
-
563
- * a ``property`` is ``:only_in => :response`` by default
564
-
565
- * a ``property`` is ``:required => :true`` by default
566
-
567
- * a ``property`` can be an ``:array_of`` objects
568
-
569
- Example
570
- _______
571
- .. code:: ruby
572
-
573
- property :example, :array_of => Hash do
574
- property :number1, Integer
575
- property :number2, Integer
576
- end
577
-
578
-
579
- Describing multiple return codes
580
- ::::::::::::::::::::::::::::::::::::::::::::::::
581
-
582
- To describe multiple possible return codes, the ``:returns`` keyword can be repeated as many times as necessary
583
- (once for each return code). Each one of the ``:returns`` entries can specify a different response format.
584
-
585
- Example
586
- _______
587
-
588
- .. code:: ruby
589
-
590
- api :GET, "/pets/:id/extra_info", "Get extra information about a pet"
591
- returns :desc => "Found a pet" do
592
- param_group :pet
593
- property 'pet_history', Hash do
594
- param_group :pet_history
595
- end
596
- end
597
- returns :code => :unprocessable_entity, :desc => "Fleas were discovered on the pet" do
598
- param_group :pet
599
- property :num_fleas, Integer, :desc => "Number of fleas on this pet"
600
- end
601
- def show_extra_info
602
- # ... implementation here
603
- end
604
-
605
-
606
-
607
- Reusing a param_group to describe inputs and outputs
608
- ::::::::::::::::::::::::::::::::::::::::::::::::::::
609
-
610
- In many cases (such as CRUD implementations), the output from certain API calls is very similar - but not
611
- identical - to the inputs of the same or other API calls.
612
-
613
- If you already have a ``:param_group`` that defines the input to a `create` or `update` routine, it would be quite
614
- frustrating to have to define a completely separate ``:param_group`` to describe the output of the `show` routine.
615
-
616
- To address such situations, it is possible to define a single ``:param_group`` which combines ``param`` and ``property``
617
- statements (as well as ``:only_in => :request`` / ``:only_in => :response``) to differentiate between fields that are
618
- only expected in the request, only included in the response, or common to both.
619
-
620
- This is somewhat analogous to the way `Action Aware params`_ work.
621
-
622
- Example
623
- _______
624
-
625
- .. code:: ruby
626
-
627
- def_param_group :user_record
628
- param :name, String # this is commong to both the request and the response
629
- param :force_update, [true, false], :only_in => :request # this does not show up in responses
630
- property :last_login, String # this shows up only in the response
631
- end
632
-
633
- api :POST, "/users", "Create a user"
634
- param_group :user_record # the :last_login field is not expected here, but :force_update is
635
- def create
636
- # ...
637
- end
638
-
639
- api :GET, "/users", "Create a user"
640
- returns :array_of => :user_record # the :last_login field will be included in the response, but :force_update will not
641
- def index
642
- # ...
643
- end
644
-
645
-
646
- Embedded response descriptions
647
- ::::::::::::::::::::::::::::::
648
-
649
- If the code creating JSON responses is encapsulated within dedicated classes, it can be more convenient to
650
- place the response descriptions outside of the controller and embed them within the response generator.
651
-
652
- To support such use cases, Apipie allows any class to provide a `describe_own_properties` class method which
653
- returns a description of the properties such a class would expose. It is then possible to specify that
654
- class in the `returns` statement instead of a `param_group`.
655
-
656
- The `describe_own_properties` method is expected to return an array of `Apipie::prop` objects, each one
657
- describing a single property.
658
-
659
- Example
660
- _______
661
-
662
- .. code:: ruby
663
-
664
- class Pet
665
- # this method is automatically called by Apipie when Pet is specified as the returned object type
666
- def self.describe_own_properties
667
- [
668
- Apipie::prop(:pet_name, 'string', {:description => 'Name of pet', :required => false}),
669
- Apipie::prop(:animal_type, 'string', {:description => 'Type of pet', :values => ["dog", "cat", "iguana", "kangaroo"]}),
670
- Apipie::additional_properties(false) # this indicates that :pet_name and :animal_type are the only properties in the response
671
- ]
672
- end
673
-
674
- # this method w
675
- def json
676
- JSON({:pet_name => @name, :animal_type => @type })
677
- end
678
- end
679
-
680
-
681
- class PetsController
682
- api :GET, "/index", "Get all pets"
683
- returns :array_of => Pet # Pet is a 'self-describing-class'
684
- def index
685
- # ...
686
- end
687
- end
688
-
689
-
690
- A use case where this is very useful is when JSON generation is done using a reflection mechanism or some
691
- other sort of declarative mechanism.
692
-
693
-
694
-
695
-
696
- The `Apipie::prop` function expects the following inputs:
697
-
698
- .. code:: ruby
699
-
700
- Apipie::prop(<property-name>, <property-type>, <options-hash> [, <array of sub-properties>])
701
-
702
- # property-name should be a symbol
703
- #
704
- # property-type can be any of the following strings:
705
- # "integer": maps to a swagger "integer" with an "int32" format
706
- # "long": maps to a swagger "integer" with an "int64" format
707
- # "number": maps to a swagger "number"(no format specifier)
708
- # "float": maps to a swagger "number" with a "float" format
709
- # "double": maps to a swagger "number" with a "double" format
710
- # "string": maps to a swagger "string" (no format specifier)
711
- # "byte": maps to a swagger "string" with a "byte" format
712
- # "binary": maps to a swagger "string" with a "binary" format
713
- # "boolean": maps to a swagger "boolean" (no format specifier)
714
- # "date": maps to a swagger "string" with a "date" format
715
- # "dateTime": maps to a swagger "string" with a "date-time" format
716
- # "password": maps to a swagger "string" with a "password" format
717
- # "object": the property has sub-properties. include <array of sub-properties> in the call.
718
- # (see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for more information
719
- # about the mapped swagger types)
720
- #
721
- # options-hash can include any of the options fields allowed in a :returns statement.
722
- # additionally, it can include the ':is_array => true', in which case the property is understood to be
723
- # an array of the described type.
724
-
725
-
726
-
727
- To describe an embedded object:
728
-
729
- .. code:: ruby
730
-
731
-
732
- #
733
- # PetWithMeasurements is a self-describing class with an embedded object
734
- #
735
- class PetWithMeasurements
736
- def self.describe_own_properties
737
- [
738
- Apipie::prop(:pet_name, 'string', {:description => 'Name of pet', :required => false}),
739
- Apipie::prop('animal_type', 'string', {:description => 'Type of pet', :values => ["dog", "cat", "iguana", "kangaroo"]}),
740
- Apipie::prop(:pet_measurements, 'object', {}, [
741
- Apipie::prop(:weight, 'number', {:description => "Weight in pounds" }),
742
- Apipie::prop(:height, 'number', {:description => "Height in inches" }),
743
- Apipie::prop(:num_legs, 'number', {:description => "Number of legs", :required => false }),
744
- Apipie::additional_properties(false)
745
- ])
746
- ]
747
- end
748
- end
749
-
750
- #
751
- # PetWithManyMeasurements is a self-describing class with an embedded array of objects
752
- #
753
- class PetWithManyMeasurements
754
- def self.describe_own_properties
755
- [
756
- Apipie::prop(:pet_name, 'string', {:description => 'Name of pet', :required => false}),
757
- Apipie::prop(:many_pet_measurements, 'object', {is_array: true}, [
758
- Apipie::prop(:weight, 'number', {:description => "Weight in pounds" }),
759
- Apipie::prop(:height, 'number', {:description => "Height in inches" }),
760
- ])
761
- ]
762
- end
763
- end
764
-
765
-
766
-
767
- Concerns
768
- --------
769
-
770
- Sometimes, the actions are not defined in the controller class
771
- directly but included from a module instead. You can load the Apipie
772
- DSL into the module by extending it with ``Apipie::DSL::Concern``.
773
-
774
- The module can be used in more controllers. Therefore there is a way to
775
- substitute parts of the documentation in the module with controller
776
- specific values. These substitutions can be stated explicitly with
777
- ``apipie_concern_subst(:key => "value")`` (needs to be called before
778
- the module is included to take effect). The substitutions are
779
- performed in the paths and descriptions of APIs and names and descriptions
780
- of params.
781
-
782
- There are some default substitutions available:
783
-
784
- :controller_path
785
- value of ``controller.controller_path``, e.g. ``api/users`` for
786
- ``Api::UsersController``. Only if not using the ``api!`` keyword.
787
-
788
- :resource_id
789
- Apipie identifier of the resource, e.g. ``users`` for
790
- ``Api::UsersController`` or set by ``resource_id``
791
-
792
- Example
793
- ~~~~~~~
794
-
795
- .. code:: ruby
796
-
797
- # users_module.rb
798
- module UsersModule
799
- extend Apipie::DSL::Concern
800
-
801
- api :GET, '/:controller_path', 'List :resource_id'
802
- def index
803
- # ...
804
- end
805
-
806
- api! 'Show a :resource'
807
- def show
808
- # ...
809
- end
810
-
811
- api :POST, '/:resource_id', "Create a :resource"
812
- param :concern, Hash, :required => true
813
- param :name, String, 'Name of a :resource'
814
- param :resource_type, ['standard','vip']
815
- end
816
- def create
817
- # ...
818
- end
819
-
820
- api :GET, '/:resource_id/:custom_subst'
821
- def custom
822
- # ...
823
- end
824
- end
825
-
826
- # users_controller.rb
827
- class UsersController < ApplicationController
828
-
829
- resource_description { resource_id 'customers' }
830
-
831
- apipie_concern_subst(:custom_subst => 'custom', :resource => 'customer')
832
- include UsersModule
833
-
834
- # the following paths are documented
835
- # api :GET, '/users'
836
- # api :GET, '/customers/:id', 'Show a customer'
837
- # api :POST, '/customers', 'Create a customer'
838
- # param :customer, :required => true do
839
- # param :name, String, 'Name of a customer'
840
- # param :customer_type, ['standard', 'vip']
841
- # end
842
- # api :GET, '/customers/:custom'
843
- end
844
-
845
-
846
- Sometimes, it's needed to extend an existing controller method with additional
847
- parameters (usually when extending exiting API from plugins/rails engines).
848
- The concern can be also used for this purposed, using `update_api` method.
849
- The params defined in this block are merged with the params of the original method
850
- in the controller this concern is included to.
851
-
852
- Example
853
- ~~~~~~~
854
-
855
- .. code:: ruby
856
-
857
- module Concerns
858
- module OauthConcern
859
- extend Apipie::DSL::Concern
860
-
861
- update_api(:create, :update) do
862
- param :user, Hash do
863
- param :oauth, String, :desc => 'oauth param'
864
- end
865
- end
866
- end
867
- end
868
-
869
- The concern needs to be included to the controller after the methods are defined
870
- (either at the end of the class, or by using
871
- ``Controller.send(:include, Concerns::OauthConcern)``.
872
-
873
-
874
- Response validation
875
- -------------------
876
-
877
- The swagger definitions created by Apipie can be used to auto-generate clients that access the
878
- described APIs. Those clients will break if the responses returned from the API do not match
879
- the declarations. As such, it is very important to include unit tests that validate the actual
880
- responses against the swagger definitions.
881
-
882
- The implemented mechanism provides two ways to include such validations in RSpec unit tests:
883
- manual (using an RSpec matcher) and automated (by injecting a test into the http operations 'get', 'post',
884
- raising an error if there is no match).
885
-
886
- Example of the manual mechanism:
887
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
888
-
889
- .. code:: ruby
890
-
891
- require 'apipie/rspec/response_validation_helper'
892
-
893
- RSpec.describe MyController, :type => :controller, :show_in_doc => true do
894
-
895
- describe "GET stuff with response validation" do
896
- render_views # this makes sure the 'get' operation will actually
897
- # return the rendered view even though this is a Controller spec
898
-
899
- it "does something" do
900
- response = get :index, {format: :json}
901
-
902
- # the following expectation will fail if the returned object
903
- # does not match the 'returns' declaration in the Controller,
904
- # or if there is no 'returns' declaration for the returned
905
- # HTTP status code
906
- expect(response).to match_declared_responses
907
- end
908
- end
909
- end
910
-
911
-
912
- Example of the automated mechanism:
913
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
914
-
915
- .. code:: ruby
916
-
917
- require 'apipie/rspec/response_validation_helper'
918
-
919
- RSpec.describe MyController, :type => :controller, :show_in_doc => true do
920
-
921
- describe "GET stuff with response validation" do
922
- render_views
923
- auto_validate_rendered_views
924
-
925
- it "does something" do
926
- get :index, {format: :json}
927
- end
928
- it "does something else" do
929
- get :another_index, {format: :json}
930
- end
931
- end
932
-
933
- describe "GET stuff without response validation" do
934
- it "does something" do
935
- get :index, {format: :json}
936
- end
937
- it "does something else" do
938
- get :another_index, {format: :json}
939
- end
940
- end
941
- end
942
-
943
-
944
- =========================
945
- Configuration Reference
946
- =========================
947
-
948
- Create a configuration file in e.g. ``/config/initializers/apipie.rb``.
949
- You can set the application name, footer text, API and documentation base URL
950
- and turn off validations. You can also choose your favorite markup language
951
- for full descriptions.
952
-
953
- app_name
954
- Name of your application; used in breadcrumbs navigation.
955
-
956
- copyright
957
- Copyright information (shown in page footer).
958
-
959
- compress_examples
960
- If ``true`` recorded examples are compressed using ``Zlib``. Useful for big test-suits.
961
-
962
- doc_base_url
963
- Documentation frontend base url.
964
-
965
- api_base_url
966
- Base url for default version of your API. To set it for specific version use ``config.api_base_url[version] = url``.
967
-
968
- default_version
969
- Default API version to be used (1.0 by default)
970
-
971
- validate
972
- Parameters validation is turned off when set to false. When set to
973
- ``:explicitly``, you must invoke parameter validation yourself by calling
974
- controller method ``apipie_validations`` (typically in a before_action).
975
- When set to ``:implicitly`` (or just true), your controller's action
976
- methods are wrapped with generated methods which call ``apipie_validations``,
977
- and then call the action method. (``:implicitly`` by default)
978
-
979
- validate_value
980
- Check the value of params against specified validators (true by
981
- default)
982
-
983
- validate_presence
984
- Check the params presence against the documentation.
985
-
986
- validate_key
987
- Check the received params to ensure they are defined in the API. (false by default)
988
-
989
- action_on_non_validated_keys
990
- Either `:raise` or `:skip`. If `validate_key` fails, raise error or delete the non-validated key from the params and log the key (`:raise` by default)
991
-
992
- process_params
993
- Process and extract the parameter defined from the params of the request
994
- to the api_params variable
995
-
996
- app_info
997
- Application long description.
998
-
999
- reload_controllers
1000
- Set to enable/disable reloading controllers (and the documentation with it). Enabled by default in development.
1001
-
1002
- api_controllers_matcher
1003
- For reloading to work properly you need to specify where your API controllers are. Can be an array if multiple paths are needed
1004
-
1005
- api_action_matcher
1006
- Determines the strategy to identity the correct controller action. Needs to be a class that implements a `.call(controller)` method
1007
-
1008
- api_routes
1009
- Set if your application uses a custom API router, different from the Rails
1010
- default
1011
-
1012
- routes_formatter
1013
- An object providing the translation from the Rails routes to the
1014
- format usable in the documentation when using the `api!` keyword. By
1015
- default, the ``Apipie::RoutesFormatter`` is used.
1016
-
1017
- markup
1018
- You can choose markup language for descriptions of your application,
1019
- resources and methods. RDoc is the default but you can choose from
1020
- Apipie::Markup::Markdown.new or Apipie::Markup::Textile.new.
1021
- In order to use Markdown you need Maruku gem and for Textile you
1022
- need RedCloth. Add those to your gemfile and run bundle if you
1023
- want to use them. You can also add any other markup language
1024
- processor.
1025
-
1026
- layout
1027
- Name of a layout template to use instead of Apipie's layout. You can use
1028
- Apipie.include_stylesheets and Apipie.include_javascripts helpers to include
1029
- Apipie's stylesheets and javascripts.
1030
-
1031
- ignored
1032
- An array of controller names (strings) (might include actions as well)
1033
- to be ignored when generationg the documentation
1034
- e.g. ``%w[Api::CommentsController Api::PostsController#post]``
1035
-
1036
- namespaced_resources
1037
- Use controller paths instead of controller names as resource id.
1038
- This prevents same named controllers overwriting each other.
1039
-
1040
- authenticate
1041
- Pass a proc in order to authenticate user. Pass nil for
1042
- no authentication (by default).
1043
-
1044
- authorize
1045
- Pass a proc in order to authorize controllers and methods. The Proc is evaluated in the controller context.
1046
-
1047
- show_all_examples
1048
- Set this to true to set show_in_doc=1 in all recorded examples
1049
-
1050
- ignore_allow_blank_false
1051
- `allow_blank: false` was incorrectly ignored up until version 0.6.0, this bug was fixed in 0.7.0
1052
- if you need the old behavior, set this to true
1053
-
1054
- link_extension
1055
- The extension to use for API pages ('.html' by default). Link extensions
1056
- in static API docs cannot be changed from '.html'.
1057
-
1058
- languages
1059
- List of languages the API documentation should be translated into. Empty by default.
1060
-
1061
- default_locale
1062
- Locale used for generating documentation when no specific locale is set.
1063
- Set to 'en' by default.
1064
-
1065
- locale
1066
- Pass locale setter/getter
1067
-
1068
- .. code:: ruby
1069
-
1070
- config.locale = lambda { |loc| loc ? FastGettext.set_locale(loc) : FastGettext.locale }
1071
-
1072
- translate
1073
- Pass proc to translate strings using the localization library your project uses.
1074
- For example see `Localization`_
1075
-
1076
- Example:
1077
-
1078
- .. code:: ruby
1079
-
1080
- Apipie.configure do |config|
1081
- config.app_name = "Test app"
1082
- config.copyright = "&copy; 2012 Pavel Pokorny"
1083
- config.doc_base_url = "/apidoc"
1084
- config.api_base_url = "/api"
1085
- config.validate = false
1086
- config.markup = Apipie::Markup::Markdown.new
1087
- config.reload_controllers = Rails.env.development?
1088
- config.api_controllers_matcher = File.join(Rails.root, "app", "controllers", "**","*.rb")
1089
- config.api_action_matcher = proc { |controller| controller.params[:action] }
1090
- config.api_routes = Rails.application.routes
1091
- config.app_info["1.0"] = "
1092
- This is where you can inform user about your application and API
1093
- in general.
1094
- "
1095
- config.authenticate = Proc.new do
1096
- authenticate_or_request_with_http_basic do |username, password|
1097
- username == "test" && password == "supersecretpassword"
1098
- end
1099
- end
1100
- config.authorize = Proc.new do |controller, method, doc|
1101
- !method # show all controller doc, but no method docs.
1102
- end
1103
- end
1104
-
1105
- checksum_path
1106
- Used in ChecksumInHeaders middleware (see `JSON checksums`_ for more info). It contains path prefix(es) where the header with checksum is added. If set to nil, checksum is added in headers in every response. e.g. ``%w[/api /apipie]``
1107
-
1108
- update_checksum
1109
- If set to true, the checksum is recalculated with every documentation_reload call
1110
-
1111
- ========================
1112
- Rails Routes Integration
1113
- ========================
1114
-
1115
- Apipie is able to load the information about the paths based on the
1116
- routes defined in the Rails application, by using the `api!` keyword
1117
- in the DSL.
1118
-
1119
- It should be usable out of box, however, one might want
1120
- to do some customization (such as omitting some implicit parameters in
1121
- the path etc.). For this kind of customizations one can create a new
1122
- formatter and pass as the ``Apipie.configuration.routes_formatter``
1123
- option, like this:
1124
-
1125
- .. code:: ruby
1126
-
1127
- class MyFormatter < Apipie::RoutesFormatter
1128
- def format_path(route)
1129
- super.gsub(/\(.*?\)/, '').gsub('//','') # hide all implicit parameters
1130
- end
1131
- end
1132
-
1133
- Apipie.configure do |config|
1134
- ...
1135
- config.routes_formatter = MyFormatter.new
1136
- ...
1137
- end
1138
-
1139
- A similar way can be used to influence things like order, or a description
1140
- of the loaded APIs, even omitting some paths if needed.
1141
-
1142
- ============
1143
- Processing
1144
- ============
1145
-
1146
- The goal is to extract and pre-process parameters of the request.
1147
-
1148
- For example Rails, by default, transforms an empty array to nil value. Perhaps
1149
- you want to transform it again into an empty array. Or you
1150
- want to support an enumeration type (comma separated values) and
1151
- you want to automatically transform this string into an array.
1152
-
1153
- To use it, set the ``process_params`` configuration variable to true.
1154
-
1155
- Also by using ``as`` you can separate your API parameter
1156
- names from the names you are using inside your code.
1157
-
1158
- To implement it, you just have to write a process_value
1159
- function in your validator:
1160
-
1161
- For an enumeration type:
1162
-
1163
- .. code:: ruby
1164
-
1165
- def process_value(value)
1166
- value ? value.split(',') : []
1167
- end
1168
-
1169
- ============
1170
- Validators
1171
- ============
1172
-
1173
- Every parameter needs to have an associated validator. For now there are some
1174
- basic validators. You can always provide your own to achieve complex
1175
- results.
1176
-
1177
- If validations are enabled (default state) the parameters of every
1178
- request are validated. If the value is wrong an +ArgumentError+ exception
1179
- is raised and can be rescued and processed. It contains a description
1180
- of the parameter value expectations. Validations can be turned off
1181
- in the configuration file.
1182
-
1183
- Here is an example of how to rescue and process a +ParamMissing+ or
1184
- +ParamInvalid+ error from within the ApplicationController.
1185
-
1186
- .. code:: ruby
1187
-
1188
- class ApplicationController < ActionController::Base
1189
-
1190
- # ParamError is superclass of ParamMissing, ParamInvalid
1191
- rescue_from Apipie::ParamError do |e|
1192
- render text: e.message, status: :unprocessable_entity
1193
- end
1194
-
1195
- # ...
1196
- end
1197
-
1198
- Parameter validation normally happens after before_actions, just before
1199
- your controller method is invoked. If you prefer to control when parameter
1200
- validation occurs, set the configuration parameter ``validate`` to ``:explicitly``.
1201
- You must then call the ``apipie_validations`` method yourself, e.g.:
1202
-
1203
- .. code:: ruby
1204
-
1205
- before_action :apipie_validations
1206
-
1207
- This is useful if you have before_actions which use parameter values: just add them
1208
- after the ``apipie_validations`` before_action.
1209
-
1210
- TypeValidator
1211
- -------------
1212
- Check the parameter type. Only String, Integer, Hash and Array are supported
1213
- for the sake of simplicity. Read more to find out how to add
1214
- your own validator.
1215
-
1216
- .. code:: ruby
1217
-
1218
- param :session, String, :desc => "user is logged in", :required => true
1219
- param :facts, Hash, :desc => "Additional optional facts about the user"
1220
-
1221
-
1222
- RegexpValidator
1223
- ---------------
1224
- Check parameter value against given regular expression.
1225
-
1226
- .. code:: ruby
1227
-
1228
- param :regexp_param, /^[0-9]* years/, :desc => "regexp param"
1229
-
1230
-
1231
- EnumValidator
1232
- --------------
1233
-
1234
- Check if parameter value is included in the given array.
1235
-
1236
- .. code:: ruby
1237
-
1238
- param :enum_param, [100, "one", "two", 1, 2], :desc => "enum validator"
1239
-
1240
-
1241
- ProcValidator
1242
- -------------
1243
-
1244
- If you need more complex validation and you know you won't reuse it, you
1245
- can use the Proc/lambda validator. Provide your own Proc, taking the value
1246
- of the parameter as the only argument. Return true if value passes validation
1247
- or return some text about what is wrong otherwise. _Don't use the keyword *return*
1248
- if you provide an instance of Proc (with lambda it is ok), just use the last
1249
- statement return property of ruby.
1250
-
1251
- .. code:: ruby
1252
-
1253
- param :proc_param, lambda { |val|
1254
- val == "param value" ? true : "The only good value is 'param value'."
1255
- }, :desc => "proc validator"
1256
-
1257
-
1258
- HashValidator
1259
- -------------
1260
-
1261
- You can describe hash parameters in depth if you provide a block with a
1262
- description of nested values.
1263
-
1264
- .. code:: ruby
1265
-
1266
- param :user, Hash, :desc => "User info" do
1267
- param :username, String, :desc => "Username for login", :required => true
1268
- param :password, String, :desc => "Password for login", :required => true
1269
- param :membership, ["standard","premium"], :desc => "User membership"
1270
- end
1271
-
1272
-
1273
- NilValidator
1274
- ------------
1275
-
1276
- In fact there isn't any NilValidator, but setting it to nil can be used to
1277
- override parameters described on the resource level.
1278
-
1279
- .. code:: ruby
1280
-
1281
- param :user, nil
1282
- def destroy
1283
- #...
1284
- end
1285
-
1286
- NumberValidator
1287
- ---------------
1288
-
1289
- Check if the parameter is a positive integer number or zero
1290
-
1291
- .. code:: ruby
1292
-
1293
- param :product_id, :number, :desc => "Identifier of the product", :required => true
1294
- param :quantity, :number, :desc => "Number of products to order", :required => true
1295
-
1296
- DecimalValidator
1297
- --------------
1298
-
1299
- Check if the parameter is a decimal number
1300
-
1301
- .. code:: ruby
1302
-
1303
- param :latitude, :decimal, :desc => "Geographic latitude", :required => true
1304
- param :longitude, :decimal, :desc => "Geographic longitude", :required => true
1305
-
1306
- ArrayValidator
1307
- --------------
1308
-
1309
- Check if the parameter is an array
1310
-
1311
- Additional options
1312
- ~~~~~~~~~~~~~~~~~
1313
-
1314
- of
1315
- Specify the type of items. If not given it accepts an array of any item type
1316
-
1317
- in
1318
- Specify an array of valid item values.
1319
-
1320
- Examples
1321
- ~~~~~~~~
1322
-
1323
- Assert `things` is an array of any items
1324
-
1325
- .. code:: ruby
1326
-
1327
- param :things, Array
1328
-
1329
- Assert `hits` must be an array of integer values
1330
-
1331
- .. code:: ruby
1332
-
1333
- param :hits, Array, of: Integer
1334
-
1335
- Assert `colors` must be an array of valid string values
1336
-
1337
- .. code:: ruby
1338
-
1339
- param :colors, Array, in: ["red", "green", "blue"]
1340
-
1341
-
1342
- The retrieving of valid items can be deferred until needed using a lambda. It is evaluated only once
1343
-
1344
- .. code:: ruby
1345
-
1346
- param :colors, Array, in: -> { Color.all.pluck(:name) }
1347
-
1348
-
1349
- NestedValidator
1350
- -------------
1351
-
1352
- You can describe nested parameters in depth if you provide a block with a
1353
- description of nested values.
1354
-
1355
- .. code:: ruby
1356
-
1357
- param :comments, Array, :desc => "User comments" do
1358
- param :name, String, :desc => "Name of the comment", :required => true
1359
- param :comment, String, :desc => "Full comment", :required => true
1360
- end
1361
-
1362
-
1363
-
1364
- Adding custom validator
1365
- -----------------------
1366
-
1367
- Only basic validators are included but it is really easy to add your own.
1368
- Create a new initializer with a subclass of Apipie::Validator::BaseValidator.
1369
- Two methods are required to implement this - instance method
1370
- :code:`validate(value)` and class method
1371
- :code:`build(param_description, argument, options, block)`.
1372
-
1373
- When searching for the validator +build+ method, every subclass of
1374
- Apipie::Validator::BaseValidator is called. The first one that returns the
1375
- constructed validator object is used.
1376
-
1377
- Example: Adding IntegerValidator
1378
-
1379
- We want to check if the parameter value is an integer like this:
1380
-
1381
- .. code:: ruby
1382
-
1383
- param :id, Integer, :desc => "Company ID"
1384
-
1385
- So we create apipie_validators.rb initializer with this content:
1386
-
1387
- .. code:: ruby
1388
-
1389
- class IntegerValidator < Apipie::Validator::BaseValidator
1390
-
1391
- def initialize(param_description, argument)
1392
- super(param_description)
1393
- @type = argument
1394
- end
1395
-
1396
- def validate(value)
1397
- return false if value.nil?
1398
- !!(value.to_s =~ /^[-+]?[0-9]+$/)
1399
- end
1400
-
1401
- def self.build(param_description, argument, options, block)
1402
- if argument == Integer
1403
- self.new(param_description, argument)
1404
- end
1405
- end
1406
-
1407
- def description
1408
- "Must be #{@type}."
1409
- end
1410
-
1411
- def expected_type
1412
- 'numeric'
1413
- end
1414
- end
1415
-
1416
- Parameters of the build method:
1417
-
1418
- param_description
1419
- Instance of Apipie::ParamDescription contains all
1420
- given information about the validated parameter.
1421
-
1422
- argument
1423
- Specified validator; in our example it is +Integer+
1424
-
1425
- options
1426
- Hash with specified options, for us just ``{:desc => "Company ID"}``
1427
-
1428
- block
1429
- Block converted into Proc, use it as you desire. In this example nil.
1430
-
1431
- If your validator includes valid values that respond true to `.blank?`, you
1432
- should also define:
1433
-
1434
- .. code:: ruby
1435
-
1436
- def ignore_allow_blank?
1437
- true
1438
- end
1439
-
1440
- so that the validation does not fail for valid values.
1441
-
1442
- ============
1443
- Versioning
1444
- ============
1445
-
1446
- Every resource/method can belong to one or more versions. The version is
1447
- specified with the `api_version` DSL keyword. When not specified,
1448
- the resource belongs to `config.default_version` ("1.0" by default)
1449
-
1450
- .. code:: ruby
1451
-
1452
- resource_description do
1453
- api_versions "1", "2"
1454
- end
1455
-
1456
- api :GET, "/api/users/", "List: users"
1457
- api_version "1"
1458
- def index
1459
- # ...
1460
- end
1461
-
1462
- api :GET, "/api/users/", "List: users", :deprecated => true
1463
-
1464
- In the example above we say the whole controller/resource is defined
1465
- for versions "1" and "2", but we override this by explicitly saying
1466
- `index` belongs only to version "1". Also, inheritance works (therefore
1467
- we can specify the api_version for the parent controller, and all
1468
- children will know about that). Routes can be flagged as deprecated,
1469
- and an annotation will be added to them when viewing in the API
1470
- documentation.
1471
-
1472
- From the Apipie API perspective, the resources belong to the version.
1473
- With versioning, there are paths like this provided by apipie:
1474
-
1475
- .. code::
1476
-
1477
- /apipie/1/users/index
1478
- /apipie/2/users/index
1479
-
1480
- When not specifying the version explicitly in the path (or in DSL),
1481
- default version (`Apipie.configuration.default_version`) is used
1482
- instead ("1.0" by default). Therefore, an application that doesn't
1483
- need versioning should work as before.
1484
-
1485
- The static page generator takes a version parameter (or uses default).
1486
-
1487
- You can specify the versions for the examples, with the `versions`
1488
- keyword. It specifies the versions the example is used for. When not
1489
- specified, it's shown in all versions with the given method.
1490
-
1491
- When referencing or quering the resource/method descripion, this
1492
- format should be used: "version#resource#method". When not specified,
1493
- the default version is used instead.
1494
-
1495
-
1496
- ========
1497
- Markup
1498
- ========
1499
-
1500
- The default markup language is `RDoc
1501
- <https://rdoc.github.io/rdoc/RDoc/Markup.html>`_. It can be changed in
1502
- the config file (``config.markup=``) to one of these:
1503
-
1504
- Markdown
1505
- Use Apipie::Markup::Markdown.new. You need Maruku gem.
1506
-
1507
- Textile
1508
- Use Apipie::Markup::Textile.new. You need RedCloth gem.
1509
-
1510
- Or provide you own object with a ``to_html(text)`` method.
1511
- For inspiration, this is how Textile markup usage is implemented:
1512
-
1513
- .. code:: ruby
1514
-
1515
- class Textile
1516
- def initialize
1517
- require 'RedCloth'
1518
- end
1519
- def to_html(text)
1520
- RedCloth.new(text).to_html
1521
- end
1522
- end
1523
-
1524
- ============
1525
- Localization
1526
- ============
1527
-
1528
- Apipie has support for localized API documentation in both formats (JSON and HTML).
1529
- Apipie uses the library I18n for localization of itself.
1530
- Check ``config/locales`` directory for available translations.
1531
-
1532
- A major part of strings in the documentation comes from the API.
1533
- As preferences regarding localization libraries differ amongst project, Apipie needs to know how to set the locale for your project,
1534
- and how to translate a string using the library your project uses. That can be done using lambdas in configuration.
1535
-
1536
- Sample configuration when your project uses FastGettext
1537
-
1538
-
1539
- .. code:: ruby
1540
-
1541
- Apipie.configure do |config|
1542
- ...
1543
- config.languages = ['en', 'cs']
1544
- config.default_locale = 'en'
1545
- config.locale = lambda { |loc| loc ? FastGettext.set_locale(loc) : FastGettext.locale }
1546
- config.translate = lambda do |str, loc|
1547
- old_loc = FastGettext.locale
1548
- FastGettext.set_locale(loc)
1549
- trans = _(str)
1550
- FastGettext.set_locale(old_loc)
1551
- trans
1552
- end
1553
- end
1554
-
1555
- And the strings in the API documentation need to be marked with the ``N_()`` function
1556
-
1557
- .. code:: ruby
1558
-
1559
- api :GET, "/users/:id", N_("Show user profile")
1560
- param :session, String, :desc => N_("user is logged in"), :required => true
1561
-
1562
-
1563
-
1564
- When your project use I18n, localization related configuration could appear as follows
1565
-
1566
- .. code:: ruby
1567
-
1568
- Apipie.configure do |config|
1569
- ...
1570
- config.languages = ['en', 'cs']
1571
- config.default_locale = 'en'
1572
- config.locale = lambda { |loc| loc ? I18n.locale = loc : I18n.locale }
1573
- config.translate = lambda do |str, loc|
1574
- return '' if str.blank?
1575
- I18n.t str, locale: loc, scope: 'doc'
1576
- end
1577
- end
1578
-
1579
- And the strings in the API documentation needs to be in the form of translation keys
1580
-
1581
- .. code:: ruby
1582
-
1583
- api :GET, "/users/:id", "show_user_profile"
1584
- param :session, String, :desc => "user_is_logged_in", :required => true
1585
-
1586
-
1587
- The localized versions of the documentation are distinguished by language in the filename.
1588
- E.g. ``doc/apidoc/apidoc.cs.html`` is static documentation in the Czech language.
1589
- If the language is missing, e.g. ``doc/apidoc/apidoc.html``,
1590
- the documentation is localized with the ``default_locale``.
1591
-
1592
- The dynamic documentation follows the same schema. The ``http://localhost:3000/apidoc/v1.cs.html`` is documentation for version '1' of the API in the Czech language. For JSON descriptions, the API applies the same format: ``http://localhost:3000/apidoc/v1.cs.json``
1593
-
1594
-
1595
- ================
1596
- Modifying Views
1597
- ================
1598
-
1599
- To modify the views of your documentation, run ``rails g apipie:views``.
1600
- This will copy the Apipie views to ``app/views/apipie/apipies`` and
1601
- ``app/views/layouts/apipie``.
1602
-
1603
-
1604
- ==============
1605
- Static files
1606
- ==============
1607
-
1608
- To generate a static version of documentation (perhaps to put it on
1609
- your project site or something), run the ``rake apipie:static`` task. It will
1610
- create a set of HTML files (multi-pages, single-page, plain) in your doc
1611
- directory. If you prefer a JSON version run ``rake apipie:static_json``.
1612
- By default the documentation for the default API version is
1613
- used. You can specify the version with ``rake apipie:static[2.0]``
1614
-
1615
- When you want to avoid any unnecessary computation in production mode,
1616
- you can generate a cache with ``rake apipie:cache`` and configure the
1617
- app to use it in production with ``config.use_cache = Rails.env.production?``
1618
-
1619
- Default cache dir is ``File.join(Rails.root, "public", "apipie-cache")``,
1620
- you can change it to where you want, example: ``config.cache_dir = File.join(Rails.root, "doc", "apidoc")``.
1621
-
1622
- If, for some complex cases, you need to generate/re-generate just part of the cache
1623
- use ``rake apipie:cache cache_part=index`` resp. ``rake apipie:cache cache_part=resources``
1624
- To generate it for different locations for further processing use ``rake apipie:cache OUT=/tmp/apipie_cache``.
1625
-
1626
- .. _Swagger:
1627
-
1628
- ====================================
1629
- Static Swagger (OpenAPI 2.0) files
1630
- ====================================
1631
-
1632
- To generate a static Swagger definition file from the api, run ``rake apipie:static_swagger_json``.
1633
- By default the documentation for the default API version is
1634
- used. You can specify the version with ``rake apipie:static_swagger_json[2.0]``. A swagger file will be
1635
- generated for each locale. The files will be generated in the same location as the static_json files, but
1636
- instead of being named ``schema_apipie[.locale].json``, they will be called ``schema_swagger[.locale].json``.
1637
-
1638
- Specifying default values for parameters
1639
- -----------------------------------------
1640
- Swagger allows method definitions to include an indication of the the default value for each parameter. To include such
1641
- indications, use ``:default_value => <some value>`` in the parameter definition DSL. For example:
1642
-
1643
- .. code:: ruby
1644
-
1645
- param :do_something, Boolean, :desc => "take an action", :required => false, :default_value => false
1646
-
1647
-
1648
- Generated Warnings
1649
- -------------------
1650
- The help identify potential improvements to your documentation, the swagger generation process issues warnings if
1651
- it identifies various shortcomings of the DSL documentation. Each warning has a code to allow selective suppression
1652
- (see swagger-specific configuration below)
1653
-
1654
- :100: missing short description for method
1655
- :101: added missing / at beginning of path
1656
- :102: no return codes specified for method
1657
- :103: a parameter is a generic Hash without an internal type specification
1658
- :104: a parameter is an 'in-path' parameter, but specified as 'not required' in the DSL
1659
- :105: a parameter is optional but does not have a default value specified
1660
- :106: a parameter was ommitted from the swagger output because it is a Hash without fields in a formData specification
1661
- :107: a path parameter is not described
1662
- :108: inferring that a parameter type is boolean because described as an enum with [false,true] values
1663
-
1664
-
1665
-
1666
- Swagger-Specific Configuration Parameters
1667
- -------------------------------------------------
1668
-
1669
- There are several configuration parameters that determine the structure of the generated swagger file:
1670
-
1671
- ``config.generator.swagger.content_type_input``
1672
- If the value is ``:form_data`` - the swagger file will indicate that the server consumes the content types
1673
- ``application/x-www-form-urlencoded`` and ``multipart/form-data``. Non-path parameters will have the
1674
- value ``"in": "formData"``. Note that parameters of type Hash that do not have any fields in them will *be ommitted*
1675
- from the resulting files, as there is no way to describe them in swagger.
1676
-
1677
- If the value is ``:json`` - the swagger file will indicate that the server consumes the content type
1678
- ``application/json``. All non-path parameters will be included in the schema of a single ``"in": "body"`` parameter
1679
- of type ``object``.
1680
-
1681
- You can specify the value of this configuration parameter as an additional input to the rake command (e.g.,
1682
- ``rake apipie:static_swagger_json[2.0,form_data]``).
1683
-
1684
- ``config.generator.swagger.json_input_uses_refs``
1685
- This parameter is only relevant if ``swagger.content_type_input`` is ``:json``.
1686
-
1687
- If ``true``: the schema of the ``"in": "body"`` parameter of each method is given its own entry in the ``definitions``
1688
- section, and is referenced using ``$ref`` from the method definition.
1689
-
1690
- If ``false``: the body parameter definitions are inlined within the method definitions.
1691
-
1692
- ``config.generator.swagger.include_warning_tags``
1693
- If ``true``: in addition to tagging methods with the name of the resource they belong to, methods for which warnings
1694
- have been issued will be tagged with.
1695
-
1696
- ``config.generator.swagger.suppress_warnings``
1697
- If ``false``: no warnings will be suppressed
1698
-
1699
- If ``true``: all warnings will be suppressed
1700
-
1701
- If an array of values (e.g., ``[100,102,107]``), only the warnings identified by the numbers in the array will be suppressed.
1702
-
1703
- ``config.generator.swagger.api_host``
1704
- The value to place in the swagger host field.
1705
-
1706
- Default is ``localhost:3000``
1707
-
1708
- If ``nil`` then then host field will not be included.
1709
-
1710
- ``config.generator.swagger.allow_additional_properties_in_response``
1711
- If ``false`` (default): response descriptions in the generated swagger will include an ``additional-properties: false``
1712
- field
1713
-
1714
- If ``true``: the ``additional-properties: false`` field will not be included in response object descriptions
1715
-
1716
- ``config.generator.swagger.schemes``
1717
- An array of transport schemes that the API supports.
1718
- This can include any combination of ``http``, ``https``, ``ws`` and ``wss``.
1719
- By default to encourage good security practices, ``['https']`` is specified.
1720
-
1721
-
1722
- ``config:swagger.security_definitions``
1723
- If the API requires authentication, you can specify details of the authentication mechanisms supported as a (Hash) value here.
1724
- See [https://swagger.io/docs/specification/2-0/authentication/] for details of what values can be specified
1725
- By default, no security is defined.
1726
-
1727
- ``config.generator.swagger.global_security``
1728
- If the API requires authentication, you can specify which of the authentication mechanisms are supported by all API operations as an Array of hashes here.
1729
- This should be used in conjunction with the mechanisms defined by ``swagger.security_definitions``.
1730
- See [https://swagger.io/docs/specification/2-0/authentication/] for details of what values can be specified
1731
- By default, no security is defined.
1732
-
1733
- ``config.generator.swagger.skip_default_tags``
1734
- By setting ``false`` (default): The resource name for e.g. ``/pets/{petId}`` will automatically be added as a tag ``pets``.
1735
- By setting ``true``: The tags needs to be explicitly added to the resource using the DSL.
1736
-
1737
- Known limitations of the current implementation
1738
- -------------------------------------------------
1739
- * There is currently no way to document the structure and content-type of the data returned from a method
1740
- * Recorded examples are currently not included in the generated swagger file
1741
- * The apipie ``formats`` value is ignored.
1742
- * It is not possible to specify the "consumed" content type on a per-method basis
1743
- * It is not possible to leverage all of the parameter type/format capabilities of swagger
1744
- * Only OpenAPI 2.0 is supported
1745
- * Responses are defined inline and not as a $ref
1746
- * It is not possible to specify per-operation security requirements (only global)
1747
-
1748
- ====================================
1749
- Dynamic Swagger generation
1750
- ====================================
1751
-
1752
- To generate swagger dynamically, use ``http://localhost:3000/apipie.json?type=swagger``.
1753
-
1754
- Note that authorization is not supported for dynamic swagger generation, so if ``config.authorize`` is defined,
1755
- dynamic swagger generation will be disabled.
1756
-
1757
- Dynamically generated swagger is not cached, and is always generated on the fly.
1758
-
1759
-
1760
- ===================
1761
- JSON checksums
1762
- ===================
1763
-
1764
- If the API client needs to be sure that the JSON didn't changed, add
1765
- the ``ApipieChecksumInHeaders`` middleware in your rails app.
1766
- It can add a checksum of the entire JSON document in the response headers.
1767
-
1768
- .. code::
1769
-
1770
- "Apipie-Checksum"=>"fb81460e7f4e78d059f826624bdf9504"
1771
-
1772
- `Apipie bindings <https://github.com/Apipie/apipie-bindings>`_ uses this feature to refresh its JSON cache.
1773
-
1774
- To set it up add the following to your ``application.rb``
1775
-
1776
- .. code::
1777
-
1778
- require 'apipie/middleware/checksum_in_headers'
1779
- # Add JSON checksum in headers for smarter caching
1780
- config.middleware.use "Apipie::Middleware::ChecksumInHeaders"
1781
-
1782
- And in your apipie initializer allow checksum calculation
1783
-
1784
- .. code::
1785
-
1786
- Apipie.configuration.update_checksum = true
1787
-
1788
-
1789
- By default the header is added to responses for ``config.doc_base_url`` and ``/api``.
1790
- It can be changed in configuration (see `Configuration Reference`_ for details).
1791
-
1792
- The checksum calculation is lazy, and done with the first request. If you run with ``use_cache = true``,
1793
- do not forget to run the rake task ``apipie:cache``.
1794
-
1795
-
1796
- ===================
1797
- Tests Integration
1798
- ===================
1799
-
1800
- Apipie integrates with automated testing in two ways. *Documentation
1801
- bootstrapping* and *examples recording*.
1802
-
1803
- Documentation Bootstrapping
1804
- ---------------------------
1805
-
1806
- Let's say you have an application without REST API documentation.
1807
- However you have a set of tests that are run against this API. A lot
1808
- of information is already included in these tests, it just needs to be
1809
- extracted somehow. Luckily, Apipie provides such a feature.
1810
-
1811
- When running the tests, set the ``APIPIE_RECORD=params`` environment
1812
- variable or call ``Apipie.record('params')`` from specs starter. You can either use it with functional tests:
1813
-
1814
- .. code::
1815
-
1816
- APIPIE_RECORD=params rake test:functionals
1817
-
1818
- or you can run your server with this param, in case you run the tests
1819
- against running server:
1820
-
1821
- .. code::
1822
-
1823
- APIPIE_RECORD=params rails server
1824
-
1825
- When the process quits, the data from requests/responses are used to
1826
- determine the documentation. It's quite raw, but it makes the initial
1827
- phase much easier.
1828
-
1829
- Examples Recording
1830
- ------------------
1831
-
1832
- You can also use the tests to generate up-to-date examples for your
1833
- code. Similar to the bootstrapping process, you can use it with functional
1834
- tests or a running server, setting ``APIPIE_RECORD=examples`` or calling ``Apipie.record('examples')`` in your specs starter.
1835
-
1836
- .. code::
1837
-
1838
- APIPIE_RECORD=examples rake test:functionals
1839
- APIPIE_RECORD=examples rails server
1840
-
1841
- The data is written into ``doc/apipie_examples.yml``. By default,
1842
- only the first example is shown for each action. You can customize
1843
- this by setting the ``show_in_doc`` attribute at each example.
1844
-
1845
- You can add a title to the examples (useful when showing more than
1846
- one example per method) by adding a 'title' attribute.
1847
-
1848
- .. code::
1849
-
1850
- --- !omap
1851
- - announcements#index:
1852
- - !omap
1853
- - title: This is a custom title for this example
1854
- - verb: :GET
1855
- - path: /api/blabla/1
1856
- - versions:
1857
- - '1.0'
1858
- - query:
1859
- - request_data:
1860
- - response_data:
1861
- ...
1862
- - code: 200
1863
- - show_in_doc: 1 # If 1, show. If 0, do not show.
1864
- - recorded: true
1865
-
1866
- In RSpec you can add metadata to examples. We can use that feature
1867
- to mark selected examples - the ones that perform the requests that we want to
1868
- show as examples in the documentation.
1869
-
1870
- For example, we can add ``show_in_doc`` to examples, like this:
1871
-
1872
- .. code:: ruby
1873
-
1874
- describe "This is the correct path" do
1875
- it "some test", :show_in_doc do
1876
- ....
1877
- end
1878
- end
1879
-
1880
- context "These are edge cases" do
1881
- it "Can't authenticate" do
1882
- ....
1883
- end
1884
-
1885
- it "record not found" do
1886
- ....
1887
- end
1888
- end
1889
-
1890
- And then configure RSpec in this way:
1891
-
1892
- .. code:: ruby
1893
-
1894
- RSpec.configure do |config|
1895
- config.treat_symbols_as_metadata_keys_with_true_values = true
1896
- config.filter_run :show_in_doc => true if ENV['APIPIE_RECORD']
1897
- end
1898
-
1899
- This way, when running in recording mode, only the tests that have been marked with the
1900
- ``:show_in_doc`` metadata will be run, and hence only those will be used as examples.
1901
-
1902
- Caveats
1903
- -------
1904
-
1905
- Make sure to enable ``config.render_views`` in your ``config/rails_helper.rb`` or
1906
- ``config/spec_helper.rb`` if you're using jbuilder, or you will get back empty results
1907
-
1908
- ====================
1909
- Bindings Generator
1910
- ====================
1911
-
1912
- In earlier versions (<= 0.0.13), there was a simple client generator
1913
- as a part of Apipie gem. As more features and users came to Apipie,
1914
- there was a greater need for changes on a per project basis. It's
1915
- hard (or even impossible) to provide a generic solution for the client
1916
- code. We also don't want to tell you what's the right way to do it
1917
- (what gems to use, how the API should look like etc.).
1918
-
1919
- Therefore you can't generate client code directly by a rake task in
1920
- further versions.
1921
-
1922
- There is, however, an even better and more flexible way to reuse your API
1923
- documentation for this purpose: using the API the Apipie
1924
- provides in the generator code. Check out our sister project
1925
- `apipie-bindings <https://github.com/Apipie/apipie-bindings>`_, as they
1926
- use exactly this approach. You also don't need to run the service,
1927
- provided it uses Apipie as a backend.
1928
-
1929
- And if you write one on your own, don't hesitate to share it with us!
1930
-
1931
- ====================
1932
- Contributing
1933
- ====================
1934
-
1935
- Then, you can install dependencies and run the test suite:
1936
-
1937
- .. code:: shell
1938
-
1939
- > bundle install
1940
- > bundle exec rspec
1941
-
1942
- ====================
1943
- Disqus Integration
1944
- ====================
1945
-
1946
- You can setup `Disqus <https://disqus.com/>`_ discussion within
1947
- your documentation. Just set the credentials in the Apipie
1948
- configuration:
1949
-
1950
- .. code:: ruby
1951
-
1952
- config.disqus_shortname = "MyProjectDoc"
1953
-
1954
- =====================
1955
- External References
1956
- =====================
1957
-
1958
- * `Getting started tutorial <https://github.com/iNecas/apipie-demo>`_ -
1959
- including examples of using the tests integration and versioning.
1960
-
1961
- * `Real-world application usage <https://github.com/Katello/katello>`_
1962
-
1963
- * `Read-world application usage with versioning <https://github.com/theforeman/foreman>`_
1964
-
1965
- * `Using Apipie API to generate bindings <https://github.com/Apipie/apipie-bindings>`_