apipie-rails 0.9.2 → 0.9.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rubocop-challenger.yml +1 -1
  3. data/.github/workflows/rubocop.yml +20 -0
  4. data/.rubocop.yml +21 -0
  5. data/.rubocop_todo.yml +222 -610
  6. data/CHANGELOG.md +16 -1
  7. data/README.rst +20 -0
  8. data/apipie-rails.gemspec +4 -0
  9. data/app/controllers/apipie/apipies_controller.rb +2 -2
  10. data/app/helpers/apipie_helper.rb +1 -1
  11. data/app/views/apipie/apipies/_deprecation.html.erb +16 -0
  12. data/app/views/apipie/apipies/_params.html.erb +7 -1
  13. data/config/locales/en.yml +7 -0
  14. data/lib/apipie/apipie_module.rb +2 -2
  15. data/lib/apipie/application.rb +16 -8
  16. data/lib/apipie/configuration.rb +13 -2
  17. data/lib/apipie/dsl_definition.rb +6 -6
  18. data/lib/apipie/error_description.rb +1 -1
  19. data/lib/apipie/errors.rb +2 -16
  20. data/lib/apipie/extractor/collector.rb +1 -1
  21. data/lib/apipie/extractor/recorder.rb +2 -2
  22. data/lib/apipie/extractor.rb +2 -2
  23. data/lib/apipie/generator/swagger/operation_id.rb +1 -1
  24. data/lib/apipie/helpers.rb +3 -3
  25. data/lib/apipie/markup.rb +9 -8
  26. data/lib/apipie/method_description.rb +1 -1
  27. data/lib/apipie/param_description/deprecation.rb +24 -0
  28. data/lib/apipie/param_description.rb +38 -11
  29. data/lib/apipie/resource_description.rb +10 -7
  30. data/lib/apipie/response_description.rb +1 -1
  31. data/lib/apipie/response_description_adapter.rb +3 -3
  32. data/lib/apipie/routing.rb +1 -1
  33. data/lib/apipie/rspec/response_validation_helper.rb +1 -1
  34. data/lib/apipie/swagger_generator.rb +6 -6
  35. data/lib/apipie/validator.rb +9 -10
  36. data/lib/apipie/version.rb +1 -1
  37. data/lib/apipie-rails.rb +1 -0
  38. data/lib/tasks/apipie.rake +11 -10
  39. data/spec/controllers/users_controller_spec.rb +8 -1
  40. data/spec/dummy/config.ru +1 -1
  41. data/spec/{controllers → lib/apipie}/apipies_controller_spec.rb +6 -2
  42. data/spec/lib/apipie/application_spec.rb +53 -0
  43. data/spec/lib/apipie/configuration_spec.rb +23 -0
  44. data/spec/lib/apipie/extractor/recorder_spec.rb +40 -0
  45. data/spec/lib/{generator → apipie/generator}/swagger/context_spec.rb +1 -0
  46. data/spec/lib/{method_description_spec.rb → apipie/method_description_spec.rb} +4 -4
  47. data/spec/lib/apipie/no_documented_method_spec.rb +17 -0
  48. data/spec/lib/apipie/param_description/deprecation_spec.rb +31 -0
  49. data/spec/lib/{param_description_spec.rb → apipie/param_description_spec.rb} +81 -1
  50. data/spec/lib/apipie/resource_description_spec.rb +91 -0
  51. data/spec/lib/apipie/response_does_not_match_swagger_schema_spec.rb +35 -0
  52. data/spec/lib/rake_spec.rb +1 -1
  53. data/spec/lib/swagger/rake_swagger_spec.rb +2 -2
  54. data/spec/lib/swagger/swagger_dsl_spec.rb +11 -5
  55. data/spec/spec_helper.rb +3 -3
  56. metadata +79 -29
  57. data/spec/lib/application_spec.rb +0 -49
  58. data/spec/lib/resource_description_spec.rb +0 -48
  59. /data/spec/{lib/swagger/response_validation_spec.rb → controllers/pets_controller_spec.rb} +0 -0
  60. /data/spec/lib/{extractor → apipie/extractor/recorder}/middleware_spec.rb +0 -0
  61. /data/spec/lib/{extractor → apipie/extractor}/writer_spec.rb +0 -0
  62. /data/spec/lib/{extractor → apipie}/extractor_spec.rb +0 -0
  63. /data/spec/lib/{file_handler_spec.rb → apipie/file_handler_spec.rb} +0 -0
  64. /data/spec/lib/{generator → apipie/generator}/swagger/operation_id_spec.rb +0 -0
  65. /data/spec/lib/{generator → apipie/generator}/swagger/param_description/builder_spec.rb +0 -0
  66. /data/spec/lib/{generator → apipie/generator}/swagger/param_description/composite_spec.rb +0 -0
  67. /data/spec/lib/{generator → apipie/generator}/swagger/param_description/description_spec.rb +0 -0
  68. /data/spec/lib/{generator → apipie/generator}/swagger/param_description/in_spec.rb +0 -0
  69. /data/spec/lib/{generator → apipie/generator}/swagger/param_description/name_spec.rb +0 -0
  70. /data/spec/lib/{generator → apipie/generator}/swagger/param_description/type_spec.rb +0 -0
  71. /data/spec/lib/{generator → apipie/generator}/swagger/param_description_spec.rb +0 -0
  72. /data/spec/lib/{generator → apipie/generator}/swagger/type_extractor_spec.rb +0 -0
  73. /data/spec/lib/{generator → apipie/generator}/swagger/warning_spec.rb +0 -0
  74. /data/spec/lib/{generator → apipie/generator}/swagger/warning_writer_spec.rb +0 -0
  75. /data/spec/lib/{method_description → apipie/method_description}/apis_service_spec.rb +0 -0
  76. /data/spec/lib/{param_group_spec.rb → apipie/param_group_spec.rb} +0 -0
  77. /data/spec/lib/{validator_spec.rb → apipie/validator_spec.rb} +0 -0
  78. /data/spec/{controllers → test_engine}/memes_controller_spec.rb +0 -0
data/CHANGELOG.md CHANGED
@@ -4,10 +4,25 @@
4
4
  Also deleted the `Gemfile` that was now a broken symlink.
5
5
  please use `export BUNDLE_GEMFILE='gemfiles/Gemfile.rails61'; bundle exec rspec` to run the test suite
6
6
 
7
+ ## [v0.9.4](https://github.com/Apipie/apipie-rails/tree/v0.9.4) (2023-04-11)
8
+ [Full Changelog](https://github.com/Apipie/apipie-rails/compare/v0.9.3...v0.9.4)
9
+ * [Fix] Separate nested resource name [#855](https://github.com/Apipie/apipie-rails/pull/855)[#455](https://github.com/Apipie/apipie-rails/issues/455) (Panos Dalitsouris)
10
+ * [Rubocop] Disable a few Rubocop Rules, run Rubocop with ruby 3.2 [#851](https://github.com/Apipie/apipie-rails/pull/851)[#853](https://github.com/Apipie/apipie-rails/pull/853)[#840](https://github.com/Apipie/apipie-rails/pull/840)[#841](https://github.com/Apipie/apipie-rails/pull/841) (Panos Dalitsouris)
11
+ * [Rubocop] More Rubocop Auto corrections [#858](https://github.com/Apipie/apipie-rails/pull/858)[#849](https://github.com/Apipie/apipie-rails/pull/849)[#850](https://github.com/Apipie/apipie-rails/pull/850)[#844](https://github.com/Apipie/apipie-rails/pull/844)[#846](https://github.com/Apipie/apipie-rails/pull/846)[#834](https://github.com/Apipie/apipie-rails/pull/834)[#847](https://github.com/Apipie/apipie-rails/pull/847) (Rubocop Challenger)
12
+
13
+ ## [v0.9.3](https://github.com/Apipie/apipie-rails/tree/v0.9.3) (2023-03-08)
14
+ [Full Changelog](https://github.com/Apipie/apipie-rails/compare/v0.9.2...v0.9.3)
15
+ * [Feature] Allow Apipie::ParamDescription to be marked as deprecated [#819](https://github.com/Apipie/apipie-rails/pull/819)[#811](https://github.com/Apipie/apipie-rails/pull/811) (Panos Dalitsouris)
16
+ * [Fix] Make html markup thread safe ([#822](https://github.com/Apipie/apipie-rails/issues/822)) (Adam Růžička)
17
+ * [Feature] Allow action matcher strategy to be configured [#821](https://github.com/Apipie/apipie-rails/pull/821) (Panos Dalitsouris)
18
+ * [CI] Run Rubocop when opening PR [#826](https://github.com/Apipie/apipie-rails/pull/826) (Panos Dalitsouris)
19
+ * [CI] Green rubocop - Fix after rubocop challenger upgrade [#829](https://github.com/Apipie/apipie-rails/pull/829) (Mathieu Jobin)
20
+ * [Rubocop] More Rubocop Auto corrections [#818](https://github.com/Apipie/apipie-rails/pull/818)[#825](https://github.com/Apipie/apipie-rails/pull/825)[#827](https://github.com/Apipie/apipie-rails/pull/827)[#837](https://github.com/Apipie/apipie-rails/pull/837)[#839](https://github.com/Apipie/apipie-rails/pull/839) (Rubocop Challenger)
21
+
7
22
  ## [v0.9.2](https://github.com/Apipie/apipie-rails/tree/v0.9.2) (2023-02-07)
8
23
  [Full Changelog](https://github.com/Apipie/apipie-rails/compare/v0.9.1...v0.9.2)
9
24
  * [Rubocop] More Rubocop Auto corrections [#795](https://github.com/Apipie/apipie-rails/pull/795)[#781](https://github.com/Apipie/apipie-rails/pull/781)[#791](https://github.com/Apipie/apipie-rails/pull/791)[#788](https://github.com/Apipie/apipie-rails/pull/788) (Rubocop Challenger)
10
- * [Fix] Can't include translation in full description ([#446](https://github.com/Apipie/apipie-rails/issues/446)) [#808](https://github.com/Apipie/apipie-rails/pull/808)( Peter Nagy)
25
+ * [Fix] Can't include translation in full description ([#446](https://github.com/Apipie/apipie-rails/issues/446)) [#808](https://github.com/Apipie/apipie-rails/pull/808) (Peter Nagy)
11
26
  * [Refactor] Move swagger param description creation [#810](https://github.com/Apipie/apipie-rails/pull/810) (Panos Dalitsouris)
12
27
  * [Rubocop] Redo rubocop TODOs, set HashSyntax config to most used style [#814](https://github.com/Apipie/apipie-rails/pull/814) (Mathieu Jobin)
13
28
  * [Fix] Swagger missing i18n [#815](https://github.com/Apipie/apipie-rails/pull/815) (@jirubio)
data/README.rst CHANGED
@@ -355,6 +355,22 @@ Example:
355
355
  #...
356
356
  end
357
357
 
358
+ deprecated
359
+ Indicates if the parameter is marked as deprecated.
360
+
361
+ Example
362
+ ~~~~~~~~
363
+
364
+ .. code:: ruby
365
+
366
+ param :pet_name, String, desc: "Name of pet", deprecated: true
367
+ param :pet_name, String, desc: "Name of pet", deprecated: 'Some deprecation info'
368
+ param :pet_name, String, desc: "Name of pet", deprecated: { in: "2.3", info: "Something", sunset: "3.0" }
369
+ def create
370
+ #...
371
+ end
372
+
373
+
358
374
  DRY with param_group
359
375
  --------------------
360
376
 
@@ -982,6 +998,9 @@ reload_controllers
982
998
  api_controllers_matcher
983
999
  For reloading to work properly you need to specify where your API controllers are. Can be an array if multiple paths are needed
984
1000
 
1001
+ api_action_matcher
1002
+ Determines the strategy to identity the correct controller action. Needs to be a class that implements a `.call(controller)` method
1003
+
985
1004
  api_routes
986
1005
  Set if your application uses a custom API router, different from the Rails
987
1006
  default
@@ -1063,6 +1082,7 @@ Example:
1063
1082
  config.markup = Apipie::Markup::Markdown.new
1064
1083
  config.reload_controllers = Rails.env.development?
1065
1084
  config.api_controllers_matcher = File.join(Rails.root, "app", "controllers", "**","*.rb")
1085
+ config.api_action_matcher = proc { |controller| controller.params[:action] }
1066
1086
  config.api_routes = Rails.application.routes
1067
1087
  config.app_info["1.0"] = "
1068
1088
  This is where you can inform user about your application and API
data/apipie-rails.gemspec CHANGED
@@ -1,4 +1,5 @@
1
1
  # -*- encoding: utf-8 -*-
2
+
2
3
  $:.push File.expand_path('lib', __dir__)
3
4
  require "apipie/version"
4
5
 
@@ -28,6 +29,9 @@ Gem::Specification.new do |s|
28
29
  s.add_development_dependency "rspec-rails", "~> 3.0"
29
30
  s.add_development_dependency "rake"
30
31
  s.add_development_dependency 'rubocop_challenger'
32
+ s.add_development_dependency 'rubocop-rails'
33
+ s.add_development_dependency 'rubocop-rspec'
34
+ s.add_development_dependency 'rubocop-performance'
31
35
  s.add_development_dependency "simplecov"
32
36
  s.add_development_dependency "sqlite3"
33
37
  end
@@ -155,7 +155,7 @@ module Apipie
155
155
  def render_from_cache
156
156
  path = Apipie.configuration.doc_base_url.dup
157
157
  # some params can contain dot, but only one in row
158
- if [:resource, :method, :format, :version].any? { |p| params[p].to_s.gsub(".", "") =~ /\W/ || params[p].to_s =~ /\.\./ }
158
+ if [:resource, :method, :format, :version].any? { |p| params[p].to_s.gsub(".", "") =~ /\W/ || params[p].to_s.include?('..') }
159
159
  head :bad_request and return
160
160
  end
161
161
 
@@ -171,7 +171,7 @@ module Apipie
171
171
  # we sanitize the params before so in ideal case, this condition
172
172
  # will be never satisfied. It's here for cases somebody adds new
173
173
  # param into the path later and forgets about sanitation.
174
- if path =~ /\.\./
174
+ if path.include?('..')
175
175
  head :bad_request and return
176
176
  end
177
177
 
@@ -1,7 +1,7 @@
1
1
  module ApipieHelper
2
2
  include ActionView::Helpers::TagHelper
3
3
 
4
- def heading(title, level=1)
4
+ def heading(title, level = 1)
5
5
  content_tag("h#{level}") do
6
6
  title
7
7
  end
@@ -0,0 +1,16 @@
1
+ <% if deprecation.present? %>
2
+ <strong><%= t('apipie.deprecation_details') %></strong>
3
+ <ul>
4
+ <% if deprecation[:deprecated_in].present? %>
5
+ <li><%= t('apipie.deprecation.attributes.deprecated_in') %>: <%= deprecation[:deprecated_in] %></li>
6
+ <% end %>
7
+
8
+ <% if deprecation[:sunset_at].present? %>
9
+ <li><%= t('apipie.deprecation.attributes.sunset_at') %>: <%= deprecation[:sunset_at] %></li>
10
+ <% end %>
11
+
12
+ <% if deprecation[:info].present? %>
13
+ <li><%= t('apipie.deprecation.attributes.info') %>: <%= deprecation[:info] %></li>
14
+ <% end %>
15
+ </ul>
16
+ <% end %>
@@ -7,7 +7,11 @@
7
7
  <% end %>
8
8
  <tr style='background-color:rgb(<%= "#{col},#{col},#{col}" %>);'>
9
9
  <td>
10
- <strong><%= param[:full_name] %> </strong><br>
10
+ <strong><%= param[:full_name] %></strong>
11
+ <% if param[:deprecated].present? %>
12
+ <code><%= t('apipie.deprecated').upcase %></code>
13
+ <% end %>
14
+ <br>
11
15
  <small>
12
16
  <%= param[:required] ? t('apipie.required') : t('apipie.optional') %>
13
17
  <%= param[:allow_nil] ? ', '+t('apipie.nil_allowed') : '' %>
@@ -29,6 +33,8 @@
29
33
  </ul>
30
34
  <%- end %>
31
35
 
36
+ <%= render partial: 'deprecation', locals: { deprecation: param[:deprecation] } %>
37
+
32
38
  <% unless param[:metadata].blank? %>
33
39
  <br>
34
40
  Metadata:
@@ -30,3 +30,10 @@ en:
30
30
  headers: Headers
31
31
  header_name: Header name
32
32
  code: Code
33
+ deprecated: Deprecated
34
+ deprecation_details: Deprecation details
35
+ deprecation:
36
+ attributes:
37
+ deprecated_in: Deprecated in
38
+ sunset_at: Sunset at
39
+ info: Info
@@ -13,7 +13,7 @@ module Apipie
13
13
  app.to_json(version, resource_name, method_name, lang)
14
14
  end
15
15
 
16
- def self.to_swagger_json(version = nil, resource_name = nil, method_name = nil, lang = nil, clear_warnings=true)
16
+ def self.to_swagger_json(version = nil, resource_name = nil, method_name = nil, lang = nil, clear_warnings = true)
17
17
  version ||= Apipie.configuration.default_version
18
18
  app.to_swagger_json(version, resource_name, method_name, lang, clear_warnings)
19
19
  end
@@ -24,7 +24,7 @@ module Apipie
24
24
  app.json_schema_for_method_response(version, controller_name, method_name, return_code, allow_nulls)
25
25
  end
26
26
 
27
- def self.json_schema_for_self_describing_class(cls, allow_nulls=true)
27
+ def self.json_schema_for_self_describing_class(cls, allow_nulls = true)
28
28
  app.json_schema_for_self_describing_class(cls, allow_nulls)
29
29
  end
30
30
 
@@ -181,9 +181,7 @@ module Apipie
181
181
  else
182
182
  raise ArgumentError.new("Resource #{resource_name} does not exists.")
183
183
  end
184
- unless resource_description.nil?
185
- resource_description.method_description(method_name.to_sym)
186
- end
184
+ resource_description&.method_description(method_name.to_sym)
187
185
  end
188
186
  alias [] get_method_description
189
187
 
@@ -242,7 +240,7 @@ module Apipie
242
240
 
243
241
  # initialize variables for gathering dsl data
244
242
  def init_env
245
- @resource_descriptions = HashWithIndifferentAccess.new { |h, version| h[version] = {} }
243
+ @resource_descriptions = ActiveSupport::HashWithIndifferentAccess.new { |h, version| h[version] = {} }
246
244
  @controller_to_resource_id = {}
247
245
  @param_groups = {}
248
246
  @swagger_generator = Apipie::SwaggerGenerator.new(self)
@@ -270,7 +268,7 @@ module Apipie
270
268
  @swagger_generator.json_schema_for_self_describing_class(cls, allow_nulls)
271
269
  end
272
270
 
273
- def to_swagger_json(version, resource_name, method_name, lang, clear_warnings=false)
271
+ def to_swagger_json(version, resource_name, method_name, lang, clear_warnings = false)
274
272
  return unless valid_search_args?(version, resource_name, method_name)
275
273
 
276
274
  # if resource_name is blank, take just resources which have some methods because
@@ -377,8 +375,18 @@ module Apipie
377
375
  @controller_to_resource_id[klass]
378
376
  elsif Apipie.configuration.namespaced_resources? && klass.respond_to?(:controller_path)
379
377
  return nil if klass == ActionController::Base
378
+
379
+ version_prefix = version_prefix(klass)
380
380
  path = klass.controller_path
381
- path.gsub(version_prefix(klass), "").gsub("/", "-")
381
+
382
+ path =
383
+ if version_prefix == '/'
384
+ path
385
+ else
386
+ path.gsub(version_prefix, '')
387
+ end
388
+
389
+ path.gsub('/', '-')
382
390
  elsif klass.respond_to?(:controller_name)
383
391
  return nil if klass == ActionController::Base
384
392
  klass.controller_name
@@ -388,11 +396,11 @@ module Apipie
388
396
  end
389
397
 
390
398
  def locale
391
- Apipie.configuration.locale.call(nil) if Apipie.configuration.locale
399
+ Apipie.configuration.locale&.call(nil)
392
400
  end
393
401
 
394
402
  def locale=(locale)
395
- Apipie.configuration.locale.call(locale) if Apipie.configuration.locale
403
+ Apipie.configuration.locale&.call(locale)
396
404
  end
397
405
 
398
406
  def translate(str, locale)
@@ -27,6 +27,16 @@ module Apipie
27
27
  # "#{Rails.root}/app/controllers/api/*.rb"
28
28
  attr_accessor :api_controllers_matcher
29
29
 
30
+ # An object that responds to a `.call(controller)` method responsible for
31
+ # matching the correct controller action
32
+ attr_reader :api_action_matcher
33
+
34
+ def api_action_matcher=(callable)
35
+ raise 'Must implement .call method' unless callable.respond_to?(:call)
36
+
37
+ @api_action_matcher = callable
38
+ end
39
+
30
40
  # set to true if you want to reload the controllers at each refresh of the
31
41
  # documentation. It requires +:api_controllers_matcher+ to be set to work
32
42
  # properly.
@@ -147,7 +157,7 @@ module Apipie
147
157
  def initialize
148
158
  @markup = Apipie::Markup::RDoc.new
149
159
  @app_name = "Another API"
150
- @app_info = HashWithIndifferentAccess.new
160
+ @app_info = ActiveSupport::HashWithIndifferentAccess.new
151
161
  @copyright = nil
152
162
  @validate = :implicitly
153
163
  @validate_value = true
@@ -155,7 +165,8 @@ module Apipie
155
165
  @validate_key = false
156
166
  @action_on_non_validated_keys = :raise
157
167
  @required_by_default = false
158
- @api_base_url = HashWithIndifferentAccess.new
168
+ @api_base_url = ActiveSupport::HashWithIndifferentAccess.new
169
+ @api_action_matcher = proc { |controller| controller.params[:action] }
159
170
  @doc_base_url = "/apipie"
160
171
  @layout = "apipie/apipie"
161
172
  @disqus_shortname = nil
@@ -96,7 +96,7 @@ module Apipie
96
96
  # # load paths from routes and don't provide description
97
97
  # api
98
98
  #
99
- def api(method, path, desc = nil, options={}) #:doc:
99
+ def api(method, path, desc = nil, options = {}) #:doc:
100
100
  return unless Apipie.active_dsl?
101
101
  _apipie_dsl_data[:api] = true
102
102
  _apipie_dsl_data[:api_args] << [method, path, desc, options]
@@ -105,7 +105,7 @@ module Apipie
105
105
  # # load paths from routes
106
106
  # api! "short description",
107
107
  #
108
- def api!(desc = nil, options={}) #:doc:
108
+ def api!(desc = nil, options = {}) #:doc:
109
109
  return unless Apipie.active_dsl?
110
110
  _apipie_dsl_data[:api] = true
111
111
  _apipie_dsl_data[:api_from_routes] = { :desc => desc, :options =>options }
@@ -145,7 +145,7 @@ module Apipie
145
145
  # EOS
146
146
  def resource_description(options = {}, &block) #:doc:
147
147
  return unless Apipie.active_dsl?
148
- raise ArgumentError, "Block expected" unless block_given?
148
+ raise ArgumentError, "Block expected" unless block
149
149
 
150
150
  dsl_data = ResourceDescriptionDsl.eval_dsl(self, &block)
151
151
  versions = dsl_data[:api_versions]
@@ -218,7 +218,7 @@ module Apipie
218
218
  # puts "hello world"
219
219
  # end
220
220
  #
221
- def error(code_or_options, desc=nil, options={}) #:doc:
221
+ def error(code_or_options, desc = nil, options = {}) #:doc:
222
222
  return unless Apipie.active_dsl?
223
223
  _apipie_dsl_data[:errors] << [code_or_options, desc, options]
224
224
  end
@@ -403,7 +403,7 @@ module Apipie
403
403
  # render json: {user: {name: "Alfred"}}
404
404
  # end
405
405
  #
406
- def returns(pgroup_or_options, desc_or_options=nil, options={}, &block) #:doc:
406
+ def returns(pgroup_or_options, desc_or_options = nil, options = {}, &block) #:doc:
407
407
  return unless Apipie.active_dsl?
408
408
 
409
409
 
@@ -508,7 +508,7 @@ module Apipie
508
508
  end
509
509
 
510
510
  def _apipie_update_meta(method_desc, dsl_data)
511
- return unless dsl_data[:meta] && dsl_data[:meta].is_a?(Hash)
511
+ return unless dsl_data[:meta].is_a?(Hash)
512
512
 
513
513
  method_desc.metadata ||= {}
514
514
  method_desc.metadata.merge!(dsl_data[:meta])
@@ -10,7 +10,7 @@ module Apipie
10
10
  options)
11
11
  end
12
12
 
13
- def initialize(code_or_options, desc=nil, options={})
13
+ def initialize(code_or_options, desc = nil, options = {})
14
14
  if code_or_options.is_a? Hash
15
15
  code_or_options.symbolize_keys!
16
16
  @code = code_or_options[:code]
data/lib/apipie/errors.rb CHANGED
@@ -60,27 +60,13 @@ module Apipie
60
60
 
61
61
  class ResponseDoesNotMatchSwaggerSchema < Error
62
62
  def initialize(controller_name, method_name, response_code, error_messages, schema, returned_object)
63
- @controller_name = controller_name
64
- @method_name = method_name
65
- @response_code = response_code
66
- @error_messages = error_messages
67
- @schema = schema
68
- @returned_object = returned_object
69
- end
70
-
71
- def to_s
72
- "Response does not match swagger schema (#{@controller_name}##{@method_name} #{@response_code}): #{@error_messages}\nSchema: #{JSON(@schema)}\nReturned object: #{@returned_object}"
63
+ super("Response does not match swagger schema (#{controller_name}##{method_name} #{response_code}): #{error_messages}\nSchema: #{JSON(schema)}\nReturned object: #{returned_object}")
73
64
  end
74
65
  end
75
66
 
76
67
  class NoDocumentedMethod < Error
77
68
  def initialize(controller_name, method_name)
78
- @method_name = method_name
79
- @controller_name = controller_name
80
- end
81
-
82
- def to_s
83
- "There is no documented method #{@controller_name}##{@method_name}"
69
+ super("There is no documented method #{controller_name}##{method_name}")
84
70
  end
85
71
  end
86
72
  end
@@ -96,7 +96,7 @@ module Apipie
96
96
  end
97
97
 
98
98
  def add_routes_info(desc)
99
- api_prefix = Apipie.api_base_url.sub(/\/$/,"")
99
+ api_prefix = Apipie.api_base_url.sub(%r{/$},"")
100
100
  desc[:api] = Apipie::Extractor.apis_from_routes[[desc[:controller].name, desc[:action]]]
101
101
  if desc[:api]
102
102
  desc[:params].each do |name, param|
@@ -9,7 +9,7 @@ module Apipie
9
9
 
10
10
  def analyse_env(env)
11
11
  @verb = env["REQUEST_METHOD"].to_sym
12
- @path = env["PATH_INFO"].sub(/^\/*/,"/")
12
+ @path = env["PATH_INFO"].sub(%r{^/*},"/")
13
13
  @query = env["QUERY_STRING"] unless env["QUERY_STRING"].blank?
14
14
  @params = Rack::Utils.parse_nested_query(@query)
15
15
  @params.merge!(env["action_dispatch.request.request_parameters"] || {})
@@ -24,7 +24,7 @@ module Apipie
24
24
 
25
25
  def analyse_controller(controller)
26
26
  @controller = controller.class
27
- @action = controller.params[:action]
27
+ @action = Apipie.configuration.api_action_matcher.call(controller)
28
28
  end
29
29
 
30
30
  def analyse_response(response)
@@ -81,7 +81,7 @@ module Apipie
81
81
  def apis_from_routes
82
82
  return @apis_from_routes if @apis_from_routes
83
83
 
84
- @api_prefix = Apipie.api_base_url.sub(/\/$/,"")
84
+ @api_prefix = Apipie.api_base_url.sub(%r{/$},"")
85
85
  populate_api_routes
86
86
  update_api_descriptions
87
87
 
@@ -157,7 +157,7 @@ module Apipie
157
157
  method_key = "#{Apipie.get_resource_name(controller.safe_constantize || next)}##{action}"
158
158
  old_apis = apis_from_docs[method_key] || []
159
159
  new_apis.each do |new_api|
160
- new_api[:path].sub!(/\(\.:format\)$/,"") if new_api[:path]
160
+ new_api[:path]&.sub!(/\(\.:format\)$/,"")
161
161
  old_api = old_apis.find do |api|
162
162
  api[:path] == "#{@api_prefix}#{new_api[:path]}"
163
163
  end
@@ -37,7 +37,7 @@ class Apipie::Generator::Swagger::OperationId
37
37
  #
38
38
  # @return [String]
39
39
  def path
40
- @path.gsub(/\//, '_').gsub(/:(\w+)/, '\1').gsub(/_$/, '')
40
+ @path.gsub(%r{/}, '_').gsub(/:(\w+)/, '\1').gsub(/_$/, '')
41
41
  end
42
42
 
43
43
  # Converts an http method like `GET` to `get` Using lowercase http method,
@@ -25,10 +25,10 @@ module Apipie
25
25
  @url_prefix << request_script_name
26
26
  @url_prefix << Apipie.configuration.doc_base_url
27
27
  end
28
- path = path.sub(/^\//,"")
28
+ path = path.sub(%r{^/},"")
29
29
  ret = "#{@url_prefix}/#{path}"
30
- ret.insert(0,"/") unless ret =~ /\A[.\/]/
31
- ret.sub!(/\/*\Z/,"")
30
+ ret.insert(0,"/") unless ret =~ %r{\A[./]}
31
+ ret.sub!(%r{/*\Z},"")
32
32
  ret
33
33
  end
34
34
 
data/lib/apipie/markup.rb CHANGED
@@ -4,6 +4,11 @@ module Apipie
4
4
 
5
5
  class RDoc
6
6
 
7
+ def initialize
8
+ require 'rdoc'
9
+ require 'rdoc/markup/to_html'
10
+ end
11
+
7
12
  def to_html(text)
8
13
  rdoc.convert(text)
9
14
  end
@@ -11,14 +16,10 @@ module Apipie
11
16
  private
12
17
 
13
18
  def rdoc
14
- @rdoc ||= begin
15
- require 'rdoc'
16
- require 'rdoc/markup/to_html'
17
- if Gem::Version.new(::RDoc::VERSION) < Gem::Version.new('4.0.0')
18
- ::RDoc::Markup::ToHtml.new()
19
- else
20
- ::RDoc::Markup::ToHtml.new(::RDoc::Options.new)
21
- end
19
+ if Gem::Version.new(::RDoc::VERSION) < Gem::Version.new('4.0.0')
20
+ ::RDoc::Markup::ToHtml.new()
21
+ else
22
+ ::RDoc::Markup::ToHtml.new(::RDoc::Options.new)
22
23
  end
23
24
  end
24
25
  end
@@ -159,7 +159,7 @@ module Apipie
159
159
  @formats || @resource._formats
160
160
  end
161
161
 
162
- def to_json(lang=nil)
162
+ def to_json(lang = nil)
163
163
  {
164
164
  :doc_url => doc_url,
165
165
  :name => @method,
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Apipie
4
+ class ParamDescription
5
+ # Data transfer object, used when param description is deprecated
6
+ class Deprecation
7
+ attr_reader :info, :deprecated_in, :sunset_at
8
+
9
+ def initialize(info: nil, deprecated_in: nil, sunset_at: nil)
10
+ @info = info
11
+ @deprecated_in = deprecated_in
12
+ @sunset_at = sunset_at
13
+ end
14
+
15
+ def to_json(*_args)
16
+ {
17
+ info: @info,
18
+ deprecated_in: @deprecated_in,
19
+ sunset_at: @sunset_at
20
+ }
21
+ end
22
+ end
23
+ end
24
+ end
@@ -97,6 +97,7 @@ module Apipie
97
97
  @validations = Array(options[:validations]).map {|v| concern_subst(Apipie.markup_to_html(v)) }
98
98
 
99
99
  @additional_properties = @options[:additional_properties]
100
+ @deprecated = @options[:deprecated] || false
100
101
  end
101
102
 
102
103
  def from_concern?
@@ -155,17 +156,25 @@ module Apipie
155
156
  end
156
157
 
157
158
  def to_json(lang = nil)
158
- hash = { :name => name.to_s,
159
- :full_name => full_name,
160
- :description => preformat_text(Apipie.app.translate(@options[:desc], lang)),
161
- :required => required,
162
- :allow_nil => allow_nil,
163
- :allow_blank => allow_blank,
164
- :validator => validator.to_s,
165
- :expected_type => validator.expected_type,
166
- :metadata => metadata,
167
- :show => show,
168
- :validations => validations }
159
+ hash = {
160
+ name: name.to_s,
161
+ full_name: full_name,
162
+ description: preformat_text(Apipie.app.translate(@options[:desc], lang)),
163
+ required: required,
164
+ allow_nil: allow_nil,
165
+ allow_blank: allow_blank,
166
+ validator: validator.to_s,
167
+ expected_type: validator.expected_type,
168
+ metadata: metadata,
169
+ show: show,
170
+ validations: validations,
171
+ deprecated: deprecated?
172
+ }
173
+
174
+ if deprecation.present?
175
+ hash[:deprecation] = deprecation.to_json
176
+ end
177
+
169
178
  if sub_params = validator.params_ordered
170
179
  hash[:params] = sub_params.map { |p| p.to_json(lang)}
171
180
  end
@@ -279,6 +288,24 @@ module Apipie
279
288
  end
280
289
  end
281
290
 
291
+ def deprecated?
292
+ @deprecated.present?
293
+ end
294
+
295
+ def deprecation
296
+ return if @deprecated.blank? || @deprecated == true
297
+
298
+ case @deprecated
299
+ when Hash
300
+ Apipie::ParamDescription::Deprecation.new(
301
+ info: @deprecated[:info],
302
+ deprecated_in: @deprecated[:in],
303
+ sunset_at: @deprecated[:sunset]
304
+ )
305
+ when String
306
+ Apipie::ParamDescription::Deprecation.new(info: @deprecated)
307
+ end
308
+ end
282
309
  end
283
310
 
284
311
  end
@@ -14,27 +14,25 @@ module Apipie
14
14
  class ResourceDescription
15
15
 
16
16
  attr_reader :controller, :_short_description, :_full_description, :_methods, :_id,
17
- :_path, :_name, :_params_args, :_returns_args, :_tag_list_arg, :_errors_args,
17
+ :_path, :_params_args, :_returns_args, :_tag_list_arg, :_errors_args,
18
18
  :_formats, :_parent, :_metadata, :_headers, :_deprecated
19
19
 
20
- def initialize(controller, resource_name, dsl_data = nil, version = nil, &block)
21
-
20
+ def initialize(controller, id, dsl_data = nil, version = nil)
22
21
  @_methods = ActiveSupport::OrderedHash.new
23
22
  @_params_args = []
24
23
  @_errors_args = []
25
24
  @_returns_args = []
26
25
 
27
26
  @controller = controller
28
- @_id = resource_name
27
+ @_id = id
29
28
  @_version = version || Apipie.configuration.default_version
30
- @_name = @_id.humanize
31
29
  @_parent = Apipie.get_resource_description(controller.superclass, version)
32
30
 
33
31
  update_from_dsl_data(dsl_data) if dsl_data
34
32
  end
35
33
 
36
34
  def update_from_dsl_data(dsl_data)
37
- @_name = dsl_data[:resource_name] if dsl_data[:resource_name]
35
+ @_resource_name = dsl_data[:resource_name] if dsl_data[:resource_name]
38
36
  @_full_description = dsl_data[:description]
39
37
  @_short_description = dsl_data[:short_description]
40
38
  @_path = dsl_data[:path] || ""
@@ -61,6 +59,11 @@ module Apipie
61
59
  @_api_base_url || @_parent.try(:_api_base_url) || Apipie.api_base_url(_version)
62
60
  end
63
61
 
62
+ def name
63
+ @name ||= @_resource_name.presence || @_id.split('-').map(&:capitalize).join('::')
64
+ end
65
+ alias _name name
66
+
64
67
  def add_method_description(method_description)
65
68
  Apipie.debug "@resource_descriptions[#{self._version}][#{self._name}]._methods[#{method_description.method}] = #{method_description}"
66
69
  @_methods[method_description.method.to_sym] = method_description
@@ -108,7 +111,7 @@ module Apipie
108
111
  :doc_url => doc_url,
109
112
  :id => _id,
110
113
  :api_url => api_url,
111
- :name => @_name,
114
+ :name => name,
112
115
  :short_description => Apipie.app.translate(@_short_description, lang),
113
116
  :full_description => Apipie.markup_to_html(Apipie.app.translate(@_full_description, lang)),
114
117
  :version => _version,
@@ -118,7 +118,7 @@ module Apipie
118
118
  end
119
119
  alias allow_additional_properties additional_properties
120
120
 
121
- def to_json(lang=nil)
121
+ def to_json(lang = nil)
122
122
  {
123
123
  :code => code,
124
124
  :description => Apipie.app.translate(description, lang),