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.
- checksums.yaml +4 -4
- data/.github/workflows/build.yml +5 -4
- data/.github/workflows/rubocop-challenger.yml +1 -3
- data/.github/workflows/rubocop.yml +1 -1
- data/.rubocop_todo.yml +22 -28
- data/CHANGELOG.md +22 -0
- data/Gemfile +2 -3
- data/README.md +2088 -0
- data/apipie-rails.gemspec +7 -1
- data/app/views/apipie/apipies/_method_detail.erb +2 -0
- data/app/views/apipie/apipies/_params.html.erb +1 -0
- data/app/views/apipie/apipies/_params_plain.html.erb +1 -0
- data/config/locales/en.yml +1 -0
- data/config/locales/ko.yml +1 -0
- data/lib/apipie/application.rb +1 -1
- data/lib/apipie/dsl_definition.rb +10 -11
- data/lib/apipie/errors.rb +1 -1
- data/lib/apipie/extractor/collector.rb +1 -1
- data/lib/apipie/extractor/recorder.rb +1 -1
- data/lib/apipie/extractor/writer.rb +2 -2
- data/lib/apipie/generator/swagger/config.rb +1 -1
- data/lib/apipie/generator/swagger/method_description/parameters_service.rb +1 -1
- data/lib/apipie/generator/swagger/method_description/response_service.rb +14 -1
- data/lib/apipie/generator/swagger/param_description/builder.rb +9 -0
- data/lib/apipie/generator/swagger/param_description/type.rb +15 -2
- data/lib/apipie/generator/swagger/resource_description_collection.rb +2 -2
- data/lib/apipie/param_description.rb +1 -1
- data/lib/apipie/response_description.rb +34 -9
- data/lib/apipie/response_description_adapter.rb +3 -3
- data/lib/apipie/routes_formatter.rb +1 -1
- data/lib/apipie/static_dispatcher.rb +7 -1
- data/lib/apipie/version.rb +1 -1
- data/lib/tasks/apipie.rake +3 -3
- data/rel-eng/gem_release.ipynb +5 -5
- data/spec/controllers/users_controller_spec.rb +1 -1
- data/spec/dummy/app/controllers/api/v2/empty_middle_controller.rb +1 -1
- data/spec/dummy/app/controllers/pets_controller.rb +2 -2
- data/spec/dummy/app/controllers/twitter_example_controller.rb +3 -3
- data/spec/lib/apipie/apipies_controller_spec.rb +1 -1
- data/spec/lib/apipie/extractor_spec.rb +1 -1
- data/spec/lib/apipie/file_handler_spec.rb +1 -1
- data/spec/lib/apipie/generator/swagger/method_description/response_schema_service_spec.rb +6 -6
- data/spec/lib/apipie/generator/swagger/method_description/response_service_spec.rb +62 -0
- data/spec/lib/apipie/generator/swagger/param_description/builder_spec.rb +14 -2
- data/spec/lib/apipie/generator/swagger/param_description/type_spec.rb +6 -1
- data/spec/lib/apipie/param_description_spec.rb +1 -1
- data/spec/lib/apipie/response_description/response_object_spec.rb +22 -0
- data/spec/lib/apipie/response_description_spec.rb +56 -0
- data/spec/lib/apipie/swagger_generator_spec.rb +2 -2
- data/spec/lib/swagger/rake_swagger_spec.rb +6 -1
- data/spec/lib/swagger/swagger_dsl_spec.rb +1 -1
- data/spec/spec_helper.rb +1 -1
- metadata +12 -6
- 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 = "© 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>`_
|