apipie-rails 0.3.6 → 0.5.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +23 -7
  3. data/CHANGELOG.md +147 -2
  4. data/Gemfile +1 -0
  5. data/Gemfile.rails41 +2 -0
  6. data/Gemfile.rails42 +10 -1
  7. data/Gemfile.rails50 +9 -0
  8. data/Gemfile.rails51 +9 -0
  9. data/Gemfile.rails60 +14 -0
  10. data/PROPOSAL_FOR_RESPONSE_DESCRIPTIONS.md +244 -0
  11. data/README.rst +570 -17
  12. data/apipie-rails.gemspec +3 -3
  13. data/app/controllers/apipie/apipies_controller.rb +48 -17
  14. data/app/views/apipie/apipies/_method_detail.erb +21 -0
  15. data/app/views/apipie/apipies/_params.html.erb +4 -2
  16. data/app/views/apipie/apipies/index.html.erb +5 -1
  17. data/app/views/apipie/apipies/resource.html.erb +3 -0
  18. data/app/views/layouts/apipie/apipie.html.erb +1 -1
  19. data/config/locales/en.yml +1 -0
  20. data/config/locales/fr.yml +31 -0
  21. data/config/locales/it.yml +31 -0
  22. data/config/locales/ja.yml +31 -0
  23. data/lib/apipie/apipie_module.rb +22 -4
  24. data/lib/apipie/application.rb +55 -28
  25. data/lib/apipie/configuration.rb +19 -3
  26. data/lib/apipie/core_ext/route.rb +9 -0
  27. data/lib/apipie/dsl_definition.rb +151 -10
  28. data/lib/apipie/error_description.rb +9 -2
  29. data/lib/apipie/errors.rb +34 -0
  30. data/lib/apipie/extractor/collector.rb +4 -0
  31. data/lib/apipie/extractor/recorder.rb +13 -12
  32. data/lib/apipie/extractor/writer.rb +83 -55
  33. data/lib/apipie/extractor.rb +10 -4
  34. data/lib/apipie/method_description.rb +51 -4
  35. data/lib/apipie/param_description.rb +56 -2
  36. data/lib/apipie/resource_description.rb +10 -3
  37. data/lib/apipie/response_description.rb +131 -0
  38. data/lib/apipie/response_description_adapter.rb +200 -0
  39. data/lib/apipie/routes_formatter.rb +1 -1
  40. data/lib/apipie/rspec/response_validation_helper.rb +194 -0
  41. data/lib/apipie/static_dispatcher.rb +3 -2
  42. data/lib/apipie/swagger_generator.rb +708 -0
  43. data/lib/apipie/tag_list_description.rb +11 -0
  44. data/lib/apipie/validator.rb +69 -8
  45. data/lib/apipie/version.rb +1 -1
  46. data/lib/apipie-rails.rb +7 -0
  47. data/lib/tasks/apipie.rake +103 -8
  48. data/spec/controllers/apipies_controller_spec.rb +52 -12
  49. data/spec/controllers/concerns_controller_spec.rb +2 -2
  50. data/spec/controllers/extended_controller_spec.rb +14 -0
  51. data/spec/controllers/memes_controller_spec.rb +10 -0
  52. data/spec/controllers/users_controller_spec.rb +115 -75
  53. data/spec/dummy/app/controllers/application_controller.rb +5 -1
  54. data/spec/dummy/app/controllers/concerns/extending_concern.rb +12 -0
  55. data/spec/dummy/app/controllers/concerns/sample_controller.rb +5 -5
  56. data/spec/dummy/app/controllers/extended_controller.rb +14 -0
  57. data/spec/dummy/app/controllers/pets_controller.rb +408 -0
  58. data/spec/dummy/app/controllers/pets_using_auto_views_controller.rb +73 -0
  59. data/spec/dummy/app/controllers/pets_using_self_describing_classes_controller.rb +95 -0
  60. data/spec/dummy/app/controllers/tagged_cats_controller.rb +32 -0
  61. data/spec/dummy/app/controllers/tagged_dogs_controller.rb +15 -0
  62. data/spec/dummy/app/controllers/twitter_example_controller.rb +5 -0
  63. data/spec/dummy/app/controllers/users_controller.rb +19 -11
  64. data/spec/dummy/components/test_engine/Gemfile +6 -0
  65. data/spec/dummy/components/test_engine/app/controllers/test_engine/application_controller.rb +4 -0
  66. data/spec/dummy/components/test_engine/app/controllers/test_engine/memes_controller.rb +37 -0
  67. data/spec/dummy/components/test_engine/config/routes.rb +3 -0
  68. data/spec/dummy/components/test_engine/db/.gitkeep +0 -0
  69. data/spec/dummy/components/test_engine/lib/test_engine.rb +7 -0
  70. data/spec/dummy/components/test_engine/test_engine.gemspec +11 -0
  71. data/spec/dummy/config/application.rb +5 -0
  72. data/spec/dummy/config/environments/development.rb +3 -0
  73. data/spec/dummy/config/environments/production.rb +3 -0
  74. data/spec/dummy/config/environments/test.rb +3 -0
  75. data/spec/dummy/config/initializers/apipie.rb +3 -1
  76. data/spec/dummy/config/routes.rb +24 -1
  77. data/spec/lib/extractor/writer_spec.rb +32 -4
  78. data/spec/lib/file_handler_spec.rb +18 -0
  79. data/spec/lib/method_description_spec.rb +34 -0
  80. data/spec/lib/swagger/openapi_2_0_schema.json +1607 -0
  81. data/spec/lib/swagger/rake_swagger_spec.rb +139 -0
  82. data/spec/lib/swagger/response_validation_spec.rb +104 -0
  83. data/spec/lib/swagger/swagger_dsl_spec.rb +658 -0
  84. data/spec/lib/validator_spec.rb +58 -0
  85. data/spec/lib/validators/array_validator_spec.rb +28 -8
  86. data/spec/spec_helper.rb +68 -0
  87. metadata +75 -23
  88. data/Gemfile +0 -7
  89. data/Gemfile.rails32 +0 -6
  90. data/Gemfile.rails40 +0 -5
  91. data/lib/apipie/client/generator.rb +0 -135
data/README.rst CHANGED
@@ -2,9 +2,9 @@
2
2
  API Documentation Tool
3
3
  ========================
4
4
 
5
- .. image:: https://travis-ci.org/Apipie/apipie-rails.png?branch=master
5
+ .. image:: https://travis-ci.org/Apipie/apipie-rails.svg?branch=master
6
6
  :target: https://travis-ci.org/Apipie/apipie-rails
7
- .. image:: https://codeclimate.com/github/Apipie/apipie-rails.png
7
+ .. image:: https://codeclimate.com/github/Apipie/apipie-rails.svg
8
8
  :target: https://codeclimate.com/github/Apipie/apipie-rails
9
9
  .. image:: https://badges.gitter.im/Apipie/apipie-rails.svg
10
10
  :alt: Join the chat at https://gitter.im/Apipie/apipie-rails
@@ -45,7 +45,7 @@ Now you can start documenting your resources and actions (see
45
45
  .. code:: ruby
46
46
 
47
47
  api :GET, '/users/:id'
48
- param :id, :number
48
+ param :id, :number, desc: 'id of the requested user'
49
49
  def show
50
50
  # ...
51
51
  end
@@ -117,6 +117,9 @@ desc (also description and full_description)
117
117
  param
118
118
  Common params for all methods defined in controller/child controllers.
119
119
 
120
+ returns
121
+ Common responses for all methods defined in controller/child controllers.
122
+
120
123
  api_base_url
121
124
  What URL is the resource available under.
122
125
 
@@ -136,6 +139,9 @@ app_info
136
139
  meta
137
140
  Hash or array with custom metadata.
138
141
 
142
+ deprecated
143
+ Boolean value indicating if the resource is marked as deprecated. (Default false)
144
+
139
145
  Example:
140
146
  ~~~~~~~~
141
147
 
@@ -152,7 +158,12 @@ Example:
152
158
  api_version "development"
153
159
  error 404, "Missing"
154
160
  error 500, "Server crashed for some <%= reason %>", :meta => {:anything => "you can think of"}
161
+ error :unprocessable_entity, "Could not save the entity."
162
+ returns :code => 403 do
163
+ property :reason, String, :desc => "Why this was forbidden"
164
+ end
155
165
  meta :author => {:name => 'John', :surname => 'Doe'}
166
+ deprecated false
156
167
  description <<-EOS
157
168
  == Long description
158
169
  Example resource for rest api documentation
@@ -206,7 +217,16 @@ api_versions (also api_version)
206
217
  What version(s) does the action belong to. (See `Versioning`_ for details.)
207
218
 
208
219
  param
209
- Look at Parameter description section for details.
220
+ Look at `Parameter description`_ section for details.
221
+
222
+ returns
223
+ Look at `Response description`_ section for details.
224
+
225
+ tags
226
+ Adds tags for grouping operations together in Swagger outputs. See `swagger`_
227
+ for more details. You can also provide tags in the `Resource Description`_
228
+ block so that they are automatically prepended to all action tags in the
229
+ controller.
210
230
 
211
231
  formats
212
232
  Method level request / response formats.
@@ -256,6 +276,15 @@ Example:
256
276
  val == "param value" ? true : "The only good value is 'param value'."
257
277
  }, :desc => "proc validator"
258
278
  param :param_with_metadata, String, :desc => "", :meta => [:your, :custom, :metadata]
279
+ returns :code => 200, :desc => "a successful response" do
280
+ property :value1, String, :desc => "A string value"
281
+ property :value2, Integer, :desc => "An integer value"
282
+ property :value3, Hash, :desc => "An object" do
283
+ property :enum1, ['v1', 'v2'], :desc => "One of 2 possible string values"
284
+ end
285
+ end
286
+ tags %w[profiles logins]
287
+ tags 'more', 'related', 'resources'
259
288
  description "method description"
260
289
  formats ['json', 'jsonp', 'xml']
261
290
  meta :message => "Some very important info"
@@ -266,7 +295,6 @@ Example:
266
295
  #...
267
296
  end
268
297
 
269
-
270
298
  Parameter Description
271
299
  ---------------------
272
300
 
@@ -288,6 +316,9 @@ required
288
316
  allow_nil
289
317
  Setting this to true means that ``nil`` can be passed.
290
318
 
319
+ allow_blank
320
+ Like ``allow_nil``, but for blank values. ``false``, ``""``, ``' '``, ``nil``, ``[]``, and ``{}`` are all blank.
321
+
291
322
  as
292
323
  Used by the processing functionality to change the name of a key params.
293
324
 
@@ -301,6 +332,13 @@ missing_message
301
332
  Specify the message to be returned if the parameter is missing as a string or Proc.
302
333
  Defaults to ``Missing parameter #{name}`` if not specified.
303
334
 
335
+ only_in
336
+ This can be set to ``:request`` or ``:response``.
337
+ Setting to ``:response`` causes the param to be ignored when used as part of a request description.
338
+ Setting to ``:request`` causes this param to be ignored when used as part of a response description.
339
+ If ``only_in`` is not specified, the param definition is used for both requests and responses.
340
+ (Note that the keyword ``property`` is similar to ``param``, but it has a ``:only_in => :response`` default).
341
+
304
342
  Example:
305
343
  ~~~~~~~~
306
344
 
@@ -421,6 +459,291 @@ with ``allow_nil`` set explicitly don't have this value changed.
421
459
  Action awareness is inherited from ancestors (in terms of
422
460
  nested params).
423
461
 
462
+
463
+ Response Description
464
+ --------------------
465
+
466
+ The response from an API call can be documented by adding a ``returns`` statement to the method
467
+ description. This is especially useful when using Apipie to auto-generate a machine-readable Swagger
468
+ definition of your API (see the `swagger`_ section for more details).
469
+
470
+ A ``returns`` statement has several possible formats:
471
+
472
+ .. code:: ruby
473
+
474
+ # format #1: reference to a param-group
475
+ returns <param-group-name> [, :code => <number>|<http-response-code-symbol>] [, :desc => <human-readable description>]
476
+
477
+ # format #2: inline response definition
478
+ returns :code => <number>|<http-response-code-symbol> [, :desc => <human-readable description>] do
479
+ # property ...
480
+ # property ...
481
+ # param_group ...
482
+ end
483
+
484
+ # format #3: describing an array-of-objects response
485
+ returns :array_of => <param-group-name> [, :code => <number>|<http-response-code-symbol>] [, :desc => <human-readable description>]
486
+
487
+
488
+ If the ``:code`` argument is ommitted, ``200`` is used.
489
+
490
+
491
+ Example
492
+ ~~~~~~~
493
+
494
+ .. code:: ruby
495
+
496
+ # ------------------------------------------------
497
+ # Example of format #1 (reference to param-group):
498
+ # ------------------------------------------------
499
+ # the param_group :pet is defined here to describe the output returned by the method below.
500
+ def_param_group :pet do
501
+ property :pet_name, String, :desc => "Name of pet"
502
+ property :animal_type, ['dog','cat','iguana','kangaroo'], :desc => "Type of pet"
503
+ end
504
+
505
+ api :GET, "/pets/:id", "Get a pet record"
506
+ returns :pet, :desc => "The pet"
507
+ def show_detailed
508
+ render JSON({:pet_name => "Skippie", :animal_type => "kangaroo"})
509
+ end
510
+
511
+ # ------------------------------------------------
512
+ # Example of format #2 (inline):
513
+ # ------------------------------------------------
514
+ api :GET, "/pets/:id/with-extra-details", "Get a detailed pet record"
515
+ returns :code => 200, :desc => "Detailed info about the pet" do
516
+ param_group :pet
517
+ property :num_legs, Integer, :desc => "How many legs the pet has"
518
+ end
519
+ def show
520
+ render JSON({:pet_name => "Barkie", :animal_type => "iguana", :legs => 4})
521
+ end
522
+
523
+ # ------------------------------------------------
524
+ # Example of format #3 (array response):
525
+ # ------------------------------------------------
526
+ api :GET, "/pets", "Get all pet records"
527
+ returns :array_of => :pet, :code => 200, :desc => "All pets"
528
+ def index
529
+ render JSON([ {:pet_name => "Skippie", :animal_type => "kangaroo"},
530
+ {:pet_name => "Woofie", :animal_type => "cat"} ])
531
+ end
532
+
533
+
534
+ Note the use of the ``property`` keyword rather than ``param``. This is the
535
+ preferred mechanism for documenting response-only fields.
536
+
537
+
538
+ The Property keyword
539
+ ::::::::::::::::::::::::::::::::::::::::::::::::
540
+
541
+ ``property`` is very similar to ``param`` with the following differences:
542
+
543
+ * a ``property`` is ``:only_in => :response`` by default
544
+
545
+ * a ``property`` is ``:required => :true`` by default
546
+
547
+ * a ``property`` can be an ``:array_of`` objects
548
+
549
+ Example
550
+ _______
551
+ .. code:: ruby
552
+
553
+ property :example, :array_of => Hash do
554
+ property :number1, Integer
555
+ property :number2, Integer
556
+ end
557
+
558
+
559
+ Describing multiple return codes
560
+ ::::::::::::::::::::::::::::::::::::::::::::::::
561
+
562
+ To describe multiple possible return codes, the ``:returns`` keyword can be repeated as many times as necessary
563
+ (once for each return code). Each one of the ``:returns`` entries can specify a different response format.
564
+
565
+ Example
566
+ _______
567
+
568
+ .. code:: ruby
569
+
570
+ api :GET, "/pets/:id/extra_info", "Get extra information about a pet"
571
+ returns :desc => "Found a pet" do
572
+ param_group :pet
573
+ property 'pet_history', Hash do
574
+ param_group :pet_history
575
+ end
576
+ end
577
+ returns :code => :unprocessable_entity, :desc => "Fleas were discovered on the pet" do
578
+ param_group :pet
579
+ property :num_fleas, Integer, :desc => "Number of fleas on this pet"
580
+ end
581
+ def show_extra_info
582
+ # ... implementation here
583
+ end
584
+
585
+
586
+
587
+ Reusing a param_group to describe inputs and outputs
588
+ ::::::::::::::::::::::::::::::::::::::::::::::::::::
589
+
590
+ In many cases (such as CRUD implementations), the output from certain API calls is very similar - but not
591
+ identical - to the inputs of the same or other API calls.
592
+
593
+ If you already have a ``:param_group`` that defines the input to a `create` or `update` routine, it would be quite
594
+ frustrating to have to define a completely separate ``:param_group`` to describe the output of the `show` routine.
595
+
596
+ To address such situations, it is possible to define a single ``:param_group`` which combines ``param`` and ``property``
597
+ statements (as well as ``:only_in => :request`` / ``:only_in => :response``) to differentiate between fields that are
598
+ only expected in the request, only included in the response, or common to both.
599
+
600
+ This is somewhat analogous to the way `Action Aware params`_ work.
601
+
602
+ Example
603
+ _______
604
+
605
+ .. code:: ruby
606
+
607
+ def_param_group :user_record
608
+ param :name, String # this is commong to both the request and the response
609
+ param :force_update, [true, false], :only_in => :request # this does not show up in responses
610
+ property :last_login, String # this shows up only in the response
611
+ end
612
+
613
+ api :POST, "/users", "Create a user"
614
+ param_group :user_record # the :last_login field is not expected here, but :force_update is
615
+ def create
616
+ # ...
617
+ end
618
+
619
+ api :GET, "/users", "Create a user"
620
+ returns :array_of => :user_record # the :last_login field will be included in the response, but :force_update will not
621
+ def index
622
+ # ...
623
+ end
624
+
625
+
626
+ Embedded response descriptions
627
+ ::::::::::::::::::::::::::::::
628
+
629
+ If the code creating JSON responses is encapsulated within dedicated classes, it can be more convenient to
630
+ place the response descriptions outside of the controller and embed them within the response generator.
631
+
632
+ To support such use cases, Apipie allows any class to provide a `describe_own_properties` class method which
633
+ returns a description of the properties such a class would expose. It is then possible to specify that
634
+ class in the `returns` statement instead of a `param_group`.
635
+
636
+ The `describe_own_properties` method is expected to return an array of `Apipie::prop` objects, each one
637
+ describing a single property.
638
+
639
+ Example
640
+ _______
641
+
642
+ .. code:: ruby
643
+
644
+ class Pet
645
+ # this method is automatically called by Apipie when Pet is specified as the returned object type
646
+ def self.describe_own_properties
647
+ [
648
+ Apipie::prop(:pet_name, 'string', {:description => 'Name of pet', :required => false}),
649
+ Apipie::prop(:animal_type, 'string', {:description => 'Type of pet', :values => ["dog", "cat", "iguana", "kangaroo"]}),
650
+ Apipie::additional_properties(false) # this indicates that :pet_name and :animal_type are the only properties in the response
651
+ ]
652
+ end
653
+
654
+ # this method w
655
+ def json
656
+ JSON({:pet_name => @name, :animal_type => @type })
657
+ end
658
+ end
659
+
660
+
661
+ class PetsController
662
+ api :GET, "/index", "Get all pets"
663
+ returns :array_of => Pet # Pet is a 'self-describing-class'
664
+ def index
665
+ # ...
666
+ end
667
+ end
668
+
669
+
670
+ A use case where this is very useful is when JSON generation is done using a reflection mechanism or some
671
+ other sort of declarative mechanism.
672
+
673
+
674
+
675
+
676
+ The `Apipie::prop` function expects the following inputs:
677
+
678
+ .. code:: ruby
679
+
680
+ Apipie::prop(<property-name>, <property-type>, <options-hash> [, <array of sub-properties>])
681
+
682
+ # property-name should be a symbol
683
+ #
684
+ # property-type can be any of the following strings:
685
+ # "integer": maps to a swagger "integer" with an "int32" format
686
+ # "long": maps to a swagger "integer" with an "int64" format
687
+ # "number": maps to a swagger "number"(no format specifier)
688
+ # "float": maps to a swagger "number" with a "float" format
689
+ # "double": maps to a swagger "number" with a "double" format
690
+ # "string": maps to a swagger "string" (no format specifier)
691
+ # "byte": maps to a swagger "string" with a "byte" format
692
+ # "binary": maps to a swagger "string" with a "binary" format
693
+ # "boolean": maps to a swagger "boolean" (no format specifier)
694
+ # "date": maps to a swagger "string" with a "date" format
695
+ # "dateTime": maps to a swagger "string" with a "date-time" format
696
+ # "password": maps to a swagger "string" with a "password" format
697
+ # "object": the property has sub-properties. include <array of sub-properties> in the call.
698
+ # (see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for more information
699
+ # about the mapped swagger types)
700
+ #
701
+ # options-hash can include any of the options fields allowed in a :returns statement.
702
+ # additionally, it can include the ':is_array => true', in which case the property is understood to be
703
+ # an array of the described type.
704
+
705
+
706
+
707
+ To describe an embedded object:
708
+
709
+ .. code:: ruby
710
+
711
+
712
+ #
713
+ # PetWithMeasurements is a self-describing class with an embedded object
714
+ #
715
+ class PetWithMeasurements
716
+ def self.describe_own_properties
717
+ [
718
+ Apipie::prop(:pet_name, 'string', {:description => 'Name of pet', :required => false}),
719
+ Apipie::prop('animal_type', 'string', {:description => 'Type of pet', :values => ["dog", "cat", "iguana", "kangaroo"]}),
720
+ Apipie::prop(:pet_measurements, 'object', {}, [
721
+ Apipie::prop(:weight, 'number', {:description => "Weight in pounds" }),
722
+ Apipie::prop(:height, 'number', {:description => "Height in inches" }),
723
+ Apipie::prop(:num_legs, 'number', {:description => "Number of legs", :required => false }),
724
+ Apipie::additional_properties(false)
725
+ ])
726
+ ]
727
+ end
728
+ end
729
+
730
+ #
731
+ # PetWithManyMeasurements is a self-describing class with an embedded array of objects
732
+ #
733
+ class PetWithManyMeasurements
734
+ def self.describe_own_properties
735
+ [
736
+ Apipie::prop(:pet_name, 'string', {:description => 'Name of pet', :required => false}),
737
+ Apipie::prop(:many_pet_measurements, 'object', {is_array: true}, [
738
+ Apipie::prop(:weight, 'number', {:description => "Weight in pounds" }),
739
+ Apipie::prop(:height, 'number', {:description => "Height in inches" }),
740
+ ])
741
+ ]
742
+ end
743
+ end
744
+
745
+
746
+
424
747
  Concerns
425
748
  --------
426
749
 
@@ -500,6 +823,103 @@ Example
500
823
  end
501
824
 
502
825
 
826
+ Sometimes, it's needed to extend an existing controller method with additional
827
+ parameters (usually when extending exiting API from plugins/rails engines).
828
+ The concern can be also used for this purposed, using `update_api` method.
829
+ The params defined in this block are merged with the params of the original method
830
+ in the controller this concern is included to.
831
+
832
+ Example
833
+ ~~~~~~~
834
+
835
+ .. code:: ruby
836
+
837
+ module Concerns
838
+ module OauthConcern
839
+ extend Apipie::DSL::Concern
840
+
841
+ update_api(:create, :update) do
842
+ param :user, Hash do
843
+ param :oauth, String, :desc => 'oauth param'
844
+ end
845
+ end
846
+ end
847
+ end
848
+
849
+ The concern needs to be included to the controller after the methods are defined
850
+ (either at the end of the class, or by using
851
+ ``Controller.send(:include, Concerns::OauthConcern)``.
852
+
853
+
854
+ Response validation
855
+ -------------------
856
+
857
+ The swagger definitions created by Apipie can be used to auto-generate clients that access the
858
+ described APIs. Those clients will break if the responses returned from the API do not match
859
+ the declarations. As such, it is very important to include unit tests that validate the actual
860
+ responses against the swagger definitions.
861
+
862
+ The implemented mechanism provides two ways to include such validations in RSpec unit tests:
863
+ manual (using an RSpec matcher) and automated (by injecting a test into the http operations 'get', 'post',
864
+ raising an error if there is no match).
865
+
866
+ Example of the manual mechanism:
867
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
868
+
869
+ .. code:: ruby
870
+
871
+ require 'apipie/rspec/response_validation_helper'
872
+
873
+ RSpec.describe MyController, :type => :controller, :show_in_doc => true do
874
+
875
+ describe "GET stuff with response validation" do
876
+ render_views # this makes sure the 'get' operation will actually
877
+ # return the rendered view even though this is a Controller spec
878
+
879
+ it "does something" do
880
+ response = get :index, {format: :json}
881
+
882
+ # the following expectation will fail if the returned object
883
+ # does not match the 'returns' declaration in the Controller,
884
+ # or if there is no 'returns' declaration for the returned
885
+ # HTTP status code
886
+ expect(response).to match_declared_responses
887
+ end
888
+ end
889
+ end
890
+
891
+
892
+ Example of the automated mechanism:
893
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
894
+
895
+ .. code:: ruby
896
+
897
+ require 'apipie/rspec/response_validation_helper'
898
+
899
+ RSpec.describe MyController, :type => :controller, :show_in_doc => true do
900
+
901
+ describe "GET stuff with response validation" do
902
+ render_views
903
+ auto_validate_rendered_views
904
+
905
+ it "does something" do
906
+ get :index, {format: :json}
907
+ end
908
+ it "does something else" do
909
+ get :another_index, {format: :json}
910
+ end
911
+ end
912
+
913
+ describe "GET stuff without response validation" do
914
+ it "does something" do
915
+ get :index, {format: :json}
916
+ end
917
+ it "does something else" do
918
+ get :another_index, {format: :json}
919
+ end
920
+ end
921
+ end
922
+
503
923
 
504
924
  =========================
505
925
  Configuration Reference
@@ -516,6 +936,9 @@ app_name
516
936
  copyright
517
937
  Copyright information (shown in page footer).
518
938
 
939
+ compress_examples
940
+ If ``true`` recorded examples are compressed using ``Zlib``. Useful for big test-suits.
941
+
519
942
  doc_base_url
520
943
  Documentation frontend base url.
521
944
 
@@ -528,7 +951,7 @@ default_version
528
951
  validate
529
952
  Parameters validation is turned off when set to false. When set to
530
953
  ``:explicitly``, you must invoke parameter validation yourself by calling
531
- controller method ``apipie_validations`` (typically in a before_filter).
954
+ controller method ``apipie_validations`` (typically in a before_action).
532
955
  When set to ``:implicitly`` (or just true), your controller's action
533
956
  methods are wrapped with generated methods which call ``apipie_validations``,
534
957
  and then call the action method. (``:implicitly`` by default)
@@ -726,17 +1149,17 @@ is raised and can be rescued and processed. It contains a description
726
1149
  of the parameter value expectations. Validations can be turned off
727
1150
  in the configuration file.
728
1151
 
729
- Parameter validation normally happens after before_filters, just before
1152
+ Parameter validation normally happens after before_actions, just before
730
1153
  your controller method is invoked. If you prefer to control when parameter
731
1154
  validation occurs, set the configuration parameter ``validate`` to ``:explicitly``.
732
1155
  You must then call the ``apipie_validations`` method yourself, e.g.:
733
1156
 
734
1157
  .. code:: ruby
735
1158
 
736
- before_filter: :apipie_validations
1159
+ before_action :apipie_validations
737
1160
 
738
- This is useful if you have before_filters which use parameter values: just add them
739
- after the ``apipie_validations`` before_filter.
1161
+ This is useful if you have before_actions which use parameter values: just add them
1162
+ after the ``apipie_validations`` before_action.
740
1163
 
741
1164
  TypeValidator
742
1165
  -------------
@@ -814,6 +1237,26 @@ override parameters described on the resource level.
814
1237
  #...
815
1238
  end
816
1239
 
1240
+ NumberValidator
1241
+ ---------------
1242
+
1243
+ Check if the parameter is a positive integer number or zero
1244
+
1245
+ .. code:: ruby
1246
+
1247
+ param :product_id, :number, :desc => "Identifier of the product", :required => true
1248
+ param :quantity, :number, :desc => "Number of products to order", :required => true
1249
+
1250
+ DecimalValidator
1251
+ --------------
1252
+
1253
+ Check if the parameter is a decimal number
1254
+
1255
+ .. code:: ruby
1256
+
1257
+ param :latitude, :decimal, :desc => "Geographic latitude", :required => true
1258
+ param :longitude, :decimal, :desc => "Geographic longitude", :required => true
1259
+
817
1260
  ArrayValidator
818
1261
  --------------
819
1262
 
@@ -995,7 +1438,7 @@ the default version is used instead.
995
1438
  ========
996
1439
 
997
1440
  The default markup language is `RDoc
998
- <http://rdoc.rubyforge.org/RDoc/Markup.html>`_. It can be changed in
1441
+ <https://rdoc.github.io/rdoc/RDoc/Markup.html>`_. It can be changed in
999
1442
  the config file (``config.markup=``) to one of these:
1000
1443
 
1001
1444
  Markdown
@@ -1068,11 +1511,8 @@ When your project use I18n, localization related configuration could appear as f
1068
1511
  config.default_locale = 'en'
1069
1512
  config.locale = lambda { |loc| loc ? I18n.locale = loc : I18n.locale }
1070
1513
  config.translate = lambda do |str, loc|
1071
- old_loc = I18n.locale
1072
- I18n.locale = loc
1073
- trans = I18n.t(str)
1074
- I18n.locale = old_loc
1075
- trans
1514
+ return '' if str.blank?
1515
+ I18n.t str, locale: loc, scope: 'doc'
1076
1516
  end
1077
1517
  end
1078
1518
 
@@ -1123,6 +1563,119 @@ If, for some complex cases, you need to generate/re-generate just part of the ca
1123
1563
  use ``rake apipie:cache cache_part=index`` resp. ``rake apipie:cache cache_part=resources``
1124
1564
  To generate it for different locations for further processing use ``rake apipie:cache OUT=/tmp/apipie_cache``.
1125
1565
 
1566
+ .. _Swagger:
1567
+
1568
+ ====================================
1569
+ Static Swagger (OpenAPI 2.0) files
1570
+ ====================================
1571
+
1572
+ To generate a static Swagger definition file from the api, run ``rake apipie:static_swagger_json``.
1573
+ By default the documentation for the default API version is
1574
+ used. You can specify the version with ``rake apipie:static_swagger_json[2.0]``. A swagger file will be
1575
+ generated for each locale. The files will be generated in the same location as the static_json files, but
1576
+ instead of being named ``schema_apipie[.locale].json``, they will be called ``schema_swagger[.locale].json``.
1577
+
1578
+ Specifying default values for parameters
1579
+ -----------------------------------------
1580
+ Swagger allows method definitions to include an indication of the the default value for each parameter. To include such
1581
+ indications, use ``:default_value => <some value>`` in the parameter definition DSL. For example:
1582
+
1583
+ .. code:: ruby
1584
+
1585
+ param :do_something, Boolean, :desc => "take an action", :required => false, :default_value => false
1586
+
1587
+
1588
+ Generated Warnings
1589
+ -------------------
1590
+ The help identify potential improvements to your documentation, the swagger generation process issues warnings if
1591
+ it identifies various shortcomings of the DSL documentation. Each warning has a code to allow selective suppression
1592
+ (see swagger-specific configuration below)
1593
+
1594
+ :100: missing short description for method
1595
+ :101: added missing / at beginning of path
1596
+ :102: no return codes specified for method
1597
+ :103: a parameter is a generic Hash without an internal type specification
1598
+ :104: a parameter is an 'in-path' parameter, but specified as 'not required' in the DSL
1599
+ :105: a parameter is optional but does not have a default value specified
1600
+ :106: a parameter was ommitted from the swagger output because it is a Hash without fields in a formData specification
1601
+ :107: a path parameter is not described
1602
+ :108: inferring that a parameter type is boolean because described as an enum with [false,true] values
1603
+
1604
+
1605
+
1606
+ Swagger-Specific Configuration Parameters
1607
+ -------------------------------------------------
1608
+
1609
+ There are several configuration parameters that determine the structure of the generated swagger file:
1610
+
1611
+ ``config.swagger_content_type_input``
1612
+ If the value is ``:form_data`` - the swagger file will indicate that the server consumes the content types
1613
+ ``application/x-www-form-urlencoded`` and ``multipart/form-data``. Non-path parameters will have the
1614
+ value ``"in": "formData"``. Note that parameters of type Hash that do not have any fields in them will *be ommitted*
1615
+ from the resulting files, as there is no way to describe them in swagger.
1616
+
1617
+ If the value is ``:json`` - the swagger file will indicate that the server consumes the content type
1618
+ ``application/json``. All non-path parameters will be included in the schema of a single ``"in": "body"`` parameter
1619
+ of type ``object``.
1620
+
1621
+ You can specify the value of this configuration parameter as an additional input to the rake command (e.g.,
1622
+ ``rake apipie:static_swagger_json[2.0,form_data]``).
1623
+
1624
+ ``config.swagger_json_input_uses_refs``
1625
+ This parameter is only relevant if ``swagger_content_type_input`` is ``:json``.
1626
+
1627
+ If ``true``: the schema of the ``"in": "body"`` parameter of each method is given its own entry in the ``definitions``
1628
+ section, and is referenced using ``$ref`` from the method definition.
1629
+
1630
+ If ``false``: the body parameter definitions are inlined within the method definitions.
1631
+
1632
+ ``config.swagger_include_warning_tags``
1633
+ If ``true``: in addition to tagging methods with the name of the resource they belong to, methods for which warnings
1634
+ have been issued will be tagged with.
1635
+
1636
+ ``config.swagger_suppress_warnings``
1637
+ If ``false``: no warnings will be suppressed
1638
+
1639
+ If ``true``: all warnings will be suppressed
1640
+
1641
+ If an array of values (e.g., ``[100,102,107]``), only the warnings identified by the numbers in the array will be suppressed.
1642
+
1643
+ ``config.swagger_api_host``
1644
+ The value to place in the swagger host field.
1645
+
1646
+ Default is ``localhost:3000``
1647
+
1648
+ If ``nil`` then then host field will not be included.
1649
+
1650
+ ``config.swagger_allow_additional_properties_in_response``
1651
+ If ``false`` (default): response descriptions in the generated swagger will include an ``additional-properties: false``
1652
+ field
1653
+
1654
+ If ``true``: the ``additional-properties: false`` field will not be included in response object descriptions
1655
+
1656
+
1657
+ Known limitations of the current implementation
1658
+ -------------------------------------------------
1659
+ * There is currently no way to document the structure and content-type of the data returned from a method
1660
+ * Recorded examples are currently not included in the generated swagger file
1661
+ * The apipie ``formats`` value is ignored.
1662
+ * It is not possible to specify the "consumed" content type on a per-method basis
1663
+ * It is not possible to leverage all of the parameter type/format capabilities of swagger
1664
+ * Only OpenAPI 2.0 is supported
1665
+ * Responses are defined inline and not as a $ref
1666
+
1667
+ ====================================
1668
+ Dynamic Swagger generation
1669
+ ====================================
1670
+
1671
+ To generate swagger dynamically, use ``http://localhost:3000/apipie.json?type=swagger``.
1672
+
1673
+ Note that authorization is not supported for dynamic swagger generation, so if ``config.authorize`` is defined,
1674
+ dynamic swagger generation will be disabled.
1675
+
1676
+ Dynamically generated swagger is not cached, and is always generated on the fly.
1677
+
1678
+
1126
1679
  ===================
1127
1680
  JSON checksums
1128
1681
  ===================
@@ -1230,7 +1783,7 @@ one example per method) by adding a 'title' attribute.
1230
1783
  - recorded: true
1231
1784
 
1232
1785
  In RSpec you can add metadata to examples. We can use that feature
1233
- to mark selected examples the ones that perform the requests that we want to
1786
+ to mark selected examples - the ones that perform the requests that we want to
1234
1787
  show as examples in the documentation.
1235
1788
 
1236
1789
  For example, we can add ``show_in_doc`` to examples, like this: