apipie-rails 1.3.0 → 1.4.0

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