apipie-rails 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/build.yml +12 -48
- data/.github/workflows/rubocop-challenger.yml +2 -2
- data/.github/workflows/rubocop.yml +2 -4
- data/.rubocop.yml +38 -37
- data/.rubocop_todo.yml +45 -64
- data/.vscode/settings.json +3 -0
- data/CHANGELOG.md +11 -2
- data/Gemfile +20 -0
- data/README.rst +6 -6
- data/app/controllers/apipie/apipies_controller.rb +3 -17
- data/gemfiles/Gemfile.tools +9 -0
- data/lib/apipie/application.rb +18 -7
- data/lib/apipie/dsl_definition.rb +1 -1
- data/lib/apipie/extractor/collector.rb +1 -1
- data/lib/apipie/extractor/recorder.rb +1 -1
- data/lib/apipie/generator/swagger/warning.rb +1 -1
- data/lib/apipie/resource_description.rb +28 -3
- data/lib/apipie/version.rb +1 -1
- data/spec/controllers/api/v2/architectures_controller_spec.rb +10 -3
- data/spec/controllers/api/v2/empty_middle_controller_spec.rb +23 -0
- data/spec/controllers/api/v2/nested/resources_controller_spec.rb +16 -0
- data/spec/controllers/api/v2/sub/footguns_controller_spec.rb +19 -0
- data/spec/dummy/app/controllers/api/v2/base_controller.rb +6 -0
- data/spec/dummy/app/controllers/api/v2/empty_middle_controller.rb +14 -0
- data/spec/dummy/app/controllers/api/v2/nested/resources_controller.rb +2 -2
- data/spec/dummy/app/controllers/api/v2/sub/footguns_controller.rb +30 -0
- data/spec/lib/apipie/apipies_controller_spec.rb +63 -19
- data/spec/lib/apipie/extractor/collector_spec.rb +57 -0
- metadata +11 -9
- data/gemfiles/Gemfile.rails50 +0 -10
- data/gemfiles/Gemfile.rails51 +0 -10
- data/gemfiles/Gemfile.rails52 +0 -10
- data/gemfiles/Gemfile.rails60 +0 -17
- data/gemfiles/Gemfile.rails61 +0 -17
- data/gemfiles/Gemfile.rails70 +0 -17
data/Gemfile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
source 'https://rubygems.org'
|
4
|
+
|
5
|
+
gemspec path: '.'
|
6
|
+
|
7
|
+
# use ENV vars, with default value as fallback for local setup
|
8
|
+
ruby(ENV['RUBY_VERSION'] || '3.2.2')
|
9
|
+
gem 'actionpack', "~> #{ENV['RAILS_VERSION'] || '7.0'}.0"
|
10
|
+
gem 'activesupport', "~> #{ENV['RAILS_VERSION'] || '7.0'}.0"
|
11
|
+
|
12
|
+
gem 'mime-types' # , '~> 3.0'
|
13
|
+
gem 'rails-controller-testing'
|
14
|
+
gem 'rspec-rails' # , '~> 5.0'
|
15
|
+
|
16
|
+
# net-smtp not included by default in Ruby 3.1
|
17
|
+
# Will be fixed by https://github.com/mikel/mail/pull/1439
|
18
|
+
gem 'net-smtp', require: false if Gem.ruby_version >= Gem::Version.new('3.1.0')
|
19
|
+
|
20
|
+
gem 'test_engine', path: './spec/dummy/components/test_engine', group: :test
|
data/README.rst
CHANGED
@@ -108,6 +108,10 @@ resource_id
|
|
108
108
|
name
|
109
109
|
Human readable name of resource. By default ``class.name.humanize`` is used.
|
110
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
|
+
|
111
115
|
short (also short_description)
|
112
116
|
Short description of the resource (it's shown on both the list of resources, and resource details)
|
113
117
|
|
@@ -1180,7 +1184,7 @@ Here is an example of how to rescue and process a +ParamMissing+ or
|
|
1180
1184
|
+ParamInvalid+ error from within the ApplicationController.
|
1181
1185
|
|
1182
1186
|
.. code:: ruby
|
1183
|
-
|
1187
|
+
|
1184
1188
|
class ApplicationController < ActionController::Base
|
1185
1189
|
|
1186
1190
|
# ParamError is superclass of ParamMissing, ParamInvalid
|
@@ -1925,14 +1929,10 @@ And if you write one on your own, don't hesitate to share it with us!
|
|
1925
1929
|
Contributing
|
1926
1930
|
====================
|
1927
1931
|
|
1928
|
-
Since this gem does not have a Gemfile, you need to specify it in your shell with:
|
1929
|
-
|
1930
|
-
.. code:: shell
|
1931
|
-
BUNDLE_GEMFILE='gemfiles/Gemfile.rails61'
|
1932
|
-
|
1933
1932
|
Then, you can install dependencies and run the test suite:
|
1934
1933
|
|
1935
1934
|
.. code:: shell
|
1935
|
+
|
1936
1936
|
> bundle install
|
1937
1937
|
> bundle exec rspec
|
1938
1938
|
|
@@ -154,26 +154,12 @@ module Apipie
|
|
154
154
|
|
155
155
|
def render_from_cache
|
156
156
|
path = Apipie.configuration.doc_base_url.dup
|
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.include?('..') }
|
159
|
-
head :bad_request and return
|
160
|
-
end
|
161
|
-
|
162
157
|
path << "/" << params[:version] if params[:version].present?
|
163
158
|
path << "/" << params[:resource] if params[:resource].present?
|
164
159
|
path << "/" << params[:method] if params[:method].present?
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
path << ".html"
|
169
|
-
end
|
170
|
-
|
171
|
-
# we sanitize the params before so in ideal case, this condition
|
172
|
-
# will be never satisfied. It's here for cases somebody adds new
|
173
|
-
# param into the path later and forgets about sanitation.
|
174
|
-
if path.include?('..')
|
175
|
-
head :bad_request and return
|
176
|
-
end
|
160
|
+
# Sanitize path against directory traversal attacks (e.g. ../../foo)
|
161
|
+
# by turning path into an absolute path before appending it to the cache dir
|
162
|
+
path = File.expand_path("#{path}.#{request.format.symbol}", '/')
|
177
163
|
|
178
164
|
cache_file = File.join(Apipie.configuration.cache_dir, path)
|
179
165
|
if File.exist?(cache_file)
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# This Gemfile is used for IDEs like VS Code that need specific gems installed
|
2
|
+
# for their tools to work properly. It is not used for the application itself.
|
3
|
+
|
4
|
+
source 'https://rubygems.org'
|
5
|
+
|
6
|
+
gem 'rubocop-rails'
|
7
|
+
gem 'rubocop-rspec'
|
8
|
+
gem 'rubocop-performance'
|
9
|
+
gem 'ruby-lsp', '~> 0.5.1'
|
data/lib/apipie/application.rb
CHANGED
@@ -122,15 +122,26 @@ module Apipie
|
|
122
122
|
# resource_description? It's used to derivate the default value of
|
123
123
|
# versions for methods.
|
124
124
|
def controller_versions(controller)
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
return [Apipie.configuration.default_version]
|
129
|
-
else
|
130
|
-
return controller_versions(controller.to_s.constantize.superclass)
|
125
|
+
value_from_parents(controller, default: [Apipie.configuration.default_version]) do |c|
|
126
|
+
ret = @controller_versions[c.to_s]
|
127
|
+
ret unless ret.empty?
|
131
128
|
end
|
132
129
|
end
|
133
130
|
|
131
|
+
# Recursively walks up the controller hierarchy looking for a value
|
132
|
+
# from the block.
|
133
|
+
# Stops at ActionController::Base.
|
134
|
+
# @param [Class] controller controller to start from
|
135
|
+
# @param [Array] args arguments passed to the block
|
136
|
+
# @param [Object] default default value to return if no value is found
|
137
|
+
# @param [Proc] block block to call with controller and args
|
138
|
+
def value_from_parents(controller, *args, default: nil, &block)
|
139
|
+
return default if controller == ActionController::Base || controller == AbstractController::Base || controller.nil?
|
140
|
+
|
141
|
+
thing = yield(controller, *args)
|
142
|
+
thing || value_from_parents(controller.superclass, *args, default: default, &block)
|
143
|
+
end
|
144
|
+
|
134
145
|
def set_controller_versions(controller, versions)
|
135
146
|
@controller_versions[controller.to_s] = versions
|
136
147
|
end
|
@@ -443,7 +454,7 @@ module Apipie
|
|
443
454
|
end
|
444
455
|
|
445
456
|
def version_prefix(klass)
|
446
|
-
version = controller_versions(klass
|
457
|
+
version = controller_versions(klass).first
|
447
458
|
base_url = get_base_url(version)
|
448
459
|
return "/" if base_url.blank?
|
449
460
|
base_url[1..-1] + "/"
|
@@ -259,7 +259,7 @@ module Apipie
|
|
259
259
|
if Apipie.configuration.validate_key?
|
260
260
|
params.reject{|k,_| %w[format controller action].include?(k.to_s) }.each_pair do |param, _|
|
261
261
|
# params allowed
|
262
|
-
if method_params.
|
262
|
+
if method_params.none? {|_,p| p.name.to_s == param.to_s}
|
263
263
|
self.class._apipie_handle_validate_key_error params, param
|
264
264
|
end
|
265
265
|
end
|
@@ -19,7 +19,7 @@ module Apipie
|
|
19
19
|
def ignore_call?(record)
|
20
20
|
return true unless record[:controller]
|
21
21
|
return true if @ignored.include?(record[:controller].name)
|
22
|
-
return true if @ignored.include?("#{Apipie.
|
22
|
+
return true if @ignored.include?("#{Apipie.get_resource_id(record[:controller].name)}##{record[:action]}")
|
23
23
|
return true unless @api_controllers_paths.include?(controller_full_path(record[:controller]))
|
24
24
|
end
|
25
25
|
|
@@ -59,7 +59,7 @@ class Apipie::Generator::Swagger::Warning
|
|
59
59
|
#
|
60
60
|
# @return [Apipie::Generator::Swagger::Warning]
|
61
61
|
def self.for_code(code, method_id, message_attributes = {})
|
62
|
-
if !CODES.
|
62
|
+
if !CODES.value?(code)
|
63
63
|
raise ArgumentError, 'Unknown warning code'
|
64
64
|
end
|
65
65
|
|
@@ -26,7 +26,9 @@ module Apipie
|
|
26
26
|
@controller = controller
|
27
27
|
@_id = id
|
28
28
|
@_version = version || Apipie.configuration.default_version
|
29
|
-
@_parent = Apipie.
|
29
|
+
@_parent = Apipie.value_from_parents(controller.superclass, version) do |parent, ver|
|
30
|
+
Apipie.get_resource_description(parent, ver)
|
31
|
+
end
|
30
32
|
|
31
33
|
update_from_dsl_data(dsl_data) if dsl_data
|
32
34
|
end
|
@@ -60,7 +62,16 @@ module Apipie
|
|
60
62
|
end
|
61
63
|
|
62
64
|
def name
|
63
|
-
@name ||=
|
65
|
+
@name ||= case resource_name
|
66
|
+
when Proc
|
67
|
+
resource_name.call(controller)
|
68
|
+
when Symbol
|
69
|
+
controller.public_send(resource_name)
|
70
|
+
when String
|
71
|
+
resource_name
|
72
|
+
else
|
73
|
+
default_name
|
74
|
+
end
|
64
75
|
end
|
65
76
|
alias _name name
|
66
77
|
|
@@ -90,7 +101,9 @@ module Apipie
|
|
90
101
|
Apipie.full_url crumbs.join('/')
|
91
102
|
end
|
92
103
|
|
93
|
-
def api_url
|
104
|
+
def api_url
|
105
|
+
"#{Apipie.api_base_url(_version)}#{@_path}"
|
106
|
+
end
|
94
107
|
|
95
108
|
def valid_method_name?(method_name)
|
96
109
|
@_methods.keys.map(&:to_s).include?(method_name.to_s)
|
@@ -123,5 +136,17 @@ module Apipie
|
|
123
136
|
}
|
124
137
|
end
|
125
138
|
|
139
|
+
protected
|
140
|
+
|
141
|
+
def resource_name
|
142
|
+
@_resource_name.presence || @_parent&.resource_name
|
143
|
+
end
|
144
|
+
|
145
|
+
private
|
146
|
+
|
147
|
+
def default_name
|
148
|
+
@_id.split('-').map(&:capitalize).join('::')
|
149
|
+
end
|
150
|
+
|
126
151
|
end
|
127
152
|
end
|
data/lib/apipie/version.rb
CHANGED
@@ -1,12 +1,19 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Api::V2::ArchitecturesController do
|
4
|
+
let(:resource_description) { Apipie.get_resource_description(described_class, "2.0") }
|
5
|
+
|
4
6
|
describe "resource description" do
|
5
|
-
|
7
|
+
describe 'version' do
|
8
|
+
subject { resource_description._version }
|
6
9
|
|
7
|
-
|
8
|
-
expect(subject._version).to eq('2.0')
|
10
|
+
it { is_expected.to eq('2.0') }
|
9
11
|
end
|
10
12
|
|
13
|
+
describe 'name' do
|
14
|
+
subject { resource_description.name }
|
15
|
+
|
16
|
+
it { is_expected.to eq('Architectures') }
|
17
|
+
end
|
11
18
|
end
|
12
19
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Api::V2::EmptyMiddleController do
|
4
|
+
let(:resource_description) { Apipie.get_resource_description(described_class, '2.0') }
|
5
|
+
|
6
|
+
describe 'resource description' do
|
7
|
+
subject { resource_description }
|
8
|
+
|
9
|
+
context 'when namespaced resources are enabled' do
|
10
|
+
before { Apipie.configuration.namespaced_resources = true }
|
11
|
+
after { Apipie.configuration.namespaced_resources = false }
|
12
|
+
|
13
|
+
# we don't actually expect the resource description to be nil, but resource IDs
|
14
|
+
# are computed at file load time, and altering the value of namespaced_resources
|
15
|
+
# after the fact doesn't change the resource ID, so it can't be found
|
16
|
+
it { is_expected.to be_nil }
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'when namespaced resources are disabled' do
|
20
|
+
it { is_expected.to be_nil }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -1,6 +1,22 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Api::V2::Nested::ResourcesController do
|
4
|
+
let(:resource_description) { Apipie.get_resource_description(described_class, "2.0") }
|
5
|
+
|
6
|
+
describe "resource description" do
|
7
|
+
describe 'version' do
|
8
|
+
subject { resource_description._version }
|
9
|
+
|
10
|
+
it { is_expected.to eq('2.0') }
|
11
|
+
end
|
12
|
+
|
13
|
+
describe 'name' do
|
14
|
+
subject { resource_description.name }
|
15
|
+
|
16
|
+
it { is_expected.to eq('Rsrcs') }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
4
20
|
describe '.get_resource_id' do
|
5
21
|
subject { Apipie.get_resource_id(Api::V2::Nested::ResourcesController) }
|
6
22
|
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Api::V2::Sub::FootgunsController do
|
4
|
+
let(:resource_description) { Apipie.get_resource_description(described_class, '2.0') }
|
5
|
+
|
6
|
+
describe 'resource description' do
|
7
|
+
describe 'version' do
|
8
|
+
subject { resource_description._version }
|
9
|
+
|
10
|
+
it { is_expected.to eq('2.0') }
|
11
|
+
end
|
12
|
+
|
13
|
+
describe 'name' do
|
14
|
+
subject { resource_description.name }
|
15
|
+
|
16
|
+
it { is_expected.to eq('snugtooF') }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Api
|
2
|
+
module V2
|
3
|
+
class EmptyMiddleController < V2::BaseController
|
4
|
+
# This is an empty controller, used to test cases where controllers
|
5
|
+
# may inherit from a middle controler that does not define a resource_description,
|
6
|
+
# but the middle controller's parent does.
|
7
|
+
|
8
|
+
def inconsequential_method
|
9
|
+
# This method is here to ensure that the controller is not empty.
|
10
|
+
# It triggers method_added, which is used to add the resource description.
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
module Api
|
2
2
|
module V2
|
3
3
|
class Nested::ResourcesController < V2::BaseController
|
4
|
-
resource_description do
|
5
|
-
name '
|
4
|
+
resource_description do
|
5
|
+
name ->(controller) { controller.controller_name.delete('aeiou').capitalize }
|
6
6
|
resource_id "resource"
|
7
7
|
end
|
8
8
|
api :GET, "/nested/resources/", "List all nested resources."
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Api
|
2
|
+
module V2
|
3
|
+
module Sub
|
4
|
+
class FootgunsController < V2::EmptyMiddleController
|
5
|
+
resource_description do
|
6
|
+
short 'Footguns are bad'
|
7
|
+
end
|
8
|
+
|
9
|
+
api :GET, '/footguns/', 'List all footguns.'
|
10
|
+
def index; end
|
11
|
+
|
12
|
+
api :GET, '/footguns/:id/', 'Show a footgun.'
|
13
|
+
def show; end
|
14
|
+
|
15
|
+
api :POST, '/footguns/', 'Create a footgun.'
|
16
|
+
def create; end
|
17
|
+
|
18
|
+
api :PUT, '/footguns/:id/', 'Update a footgun.'
|
19
|
+
param :footgun, Hash, :required => true do
|
20
|
+
param :name, String
|
21
|
+
end
|
22
|
+
def update; end
|
23
|
+
|
24
|
+
api! 'Delete a footgun.'
|
25
|
+
api_version '2.0' # forces removal of the method description
|
26
|
+
def destroy; end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -258,12 +258,12 @@ describe Apipie::ApipiesController, type: :controller do
|
|
258
258
|
|
259
259
|
before do
|
260
260
|
FileUtils.rm_r(cache_dir) if File.exist?(cache_dir)
|
261
|
-
FileUtils.mkdir_p(File.join(cache_dir, "apidoc", "v1", "resource"))
|
261
|
+
FileUtils.mkdir_p(File.join(cache_dir, "apidoc", "v1", "resource-with-namespace"))
|
262
262
|
File.open(File.join(cache_dir, "apidoc", "v1.html"), "w") { |f| f << "apidoc.html cache v1" }
|
263
263
|
File.open(File.join(cache_dir, "apidoc", "v2.html"), "w") { |f| f << "apidoc.html cache v2" }
|
264
264
|
File.open(File.join(cache_dir, "apidoc", "v1.json"), "w") { |f| f << "apidoc.json cache" }
|
265
|
-
File.open(File.join(cache_dir, "apidoc", "v1", "resource.html"), "w") { |f| f << "resource.html cache" }
|
266
|
-
File.open(File.join(cache_dir, "apidoc", "v1", "resource", "method.html"), "w") { |f| f << "method.html cache" }
|
265
|
+
File.open(File.join(cache_dir, "apidoc", "v1", "resource-with-namespace.html"), "w") { |f| f << "resource-with-namespace.html cache" }
|
266
|
+
File.open(File.join(cache_dir, "apidoc", "v1", "resource-with-namespace", "method.html"), "w") { |f| f << "method.html cache" }
|
267
267
|
|
268
268
|
Apipie.configuration.use_cache = true
|
269
269
|
@orig_cache_dir = Apipie.configuration.cache_dir
|
@@ -279,24 +279,68 @@ describe Apipie::ApipiesController, type: :controller do
|
|
279
279
|
# FileUtils.rm_r(cache_dir) if File.exist?(cache_dir)
|
280
280
|
end
|
281
281
|
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
282
|
+
context 'when the file exists' do
|
283
|
+
it "uses the file in cache dir instead of generating the content on runtime" do
|
284
|
+
get :index
|
285
|
+
expect(response.body).to eq("apidoc.html cache v1")
|
286
|
+
|
287
|
+
get :index, :params => { :version => 'v1' }
|
288
|
+
expect(response.body).to eq("apidoc.html cache v1")
|
289
|
+
|
290
|
+
get :index, :params => { :version => 'v2' }
|
291
|
+
expect(response.body).to eq("apidoc.html cache v2")
|
292
|
+
|
293
|
+
get :index, :params => { :version => 'v1', :format => "html" }
|
294
|
+
expect(response.body).to eq("apidoc.html cache v1")
|
295
|
+
|
296
|
+
get :index, :params => { :version => 'v1', :format => "json" }
|
297
|
+
expect(response.body).to eq("apidoc.json cache")
|
298
|
+
|
299
|
+
get :index, :params => { :version => 'v1', :format => "html", :resource => "resource-with-namespace" }
|
300
|
+
expect(response.body).to eq("resource-with-namespace.html cache")
|
301
|
+
|
302
|
+
get :index, :params => { :version => 'v1', :format => "html", :resource => "resource-with-namespace", :method => "method" }
|
303
|
+
expect(response.body).to eq("method.html cache")
|
304
|
+
end
|
297
305
|
end
|
298
306
|
|
299
|
-
|
307
|
+
context 'when the file does not exist' do
|
308
|
+
it 'returns a not found' do
|
309
|
+
get :index, :params => { :version => 'v3-does-not-exist' }
|
310
|
+
expect(response).to have_http_status(:not_found)
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
context 'preventing path traversal' do
|
315
|
+
context 'when resource contains ..' do
|
316
|
+
it "returns a not found" do
|
317
|
+
get :index, :params => { :version => 'v1', :format => "html", :resource => "../resource-with-namespace", :method => "method" }
|
318
|
+
expect(response).to have_http_status(:not_found)
|
319
|
+
end
|
320
|
+
end
|
300
321
|
|
322
|
+
context 'when method contains ..' do
|
323
|
+
it "returns a not found" do
|
324
|
+
get :index, :params => { :version => 'v1', :format => "html", :resource => "resource-with-namespace", :method => "../method" }
|
325
|
+
expect(response).to have_http_status(:not_found)
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
context 'when version contains ..' do
|
330
|
+
it "returns a not found" do
|
331
|
+
get :index, :params => { :version => '../v1', :format => "html", :resource => "resource-with-namespace", :method => "method" }
|
332
|
+
expect(response).to have_http_status(:not_found)
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
context 'when format contains ..' do
|
337
|
+
it "returns a not found" do
|
338
|
+
get :index, :params => { :version => 'v1', :format => "../html", :resource => "resource-with-namespace", :method => "method" }
|
339
|
+
expect(response).to have_http_status(:not_found)
|
340
|
+
end
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
344
|
+
end
|
301
345
|
|
302
346
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Apipie::Extractor::Collector do
|
6
|
+
let(:recorder) { described_class.new }
|
7
|
+
|
8
|
+
describe '#ignore_call?' do
|
9
|
+
subject { recorder.ignore_call?(record) }
|
10
|
+
|
11
|
+
let(:record) { { controller: controller, action: action } }
|
12
|
+
let(:controller) { ActionController::Base }
|
13
|
+
let(:action) { nil }
|
14
|
+
|
15
|
+
context 'when controller is nil' do
|
16
|
+
let(:controller) { nil }
|
17
|
+
|
18
|
+
it { is_expected.to be true }
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'when controller is ignored' do
|
22
|
+
before do
|
23
|
+
allow(Apipie.configuration).to receive(:ignored_by_recorder).and_return(['ActionController::Bas'])
|
24
|
+
end
|
25
|
+
|
26
|
+
it { is_expected.to be true }
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'when resource#method is ignored' do
|
30
|
+
let(:action) { 'ignored_action' }
|
31
|
+
|
32
|
+
before do
|
33
|
+
allow(Apipie.configuration).to receive(:ignored_by_recorder).and_return(['ActionController::Bas#ignored_action'])
|
34
|
+
end
|
35
|
+
|
36
|
+
it { is_expected.to be true }
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'when controller is not an API controller' do
|
40
|
+
before do
|
41
|
+
allow(Apipie::Extractor).to receive(:controller_path).with('action_controller/base').and_return('foo')
|
42
|
+
allow(Apipie).to receive(:api_controllers_paths).and_return([])
|
43
|
+
end
|
44
|
+
|
45
|
+
it { is_expected.to be true }
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'when controller is an API controller' do
|
49
|
+
before do
|
50
|
+
allow(Apipie::Extractor).to receive(:controller_path).with('action_controller/base').and_return('foo')
|
51
|
+
allow(Apipie).to receive(:api_controllers_paths).and_return(['foo'])
|
52
|
+
end
|
53
|
+
|
54
|
+
it { is_expected.to be_falsey }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: apipie-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pavel Pokorny
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2023-
|
12
|
+
date: 2023-06-03 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: actionpack
|
@@ -208,8 +208,10 @@ files:
|
|
208
208
|
- ".rspec"
|
209
209
|
- ".rubocop.yml"
|
210
210
|
- ".rubocop_todo.yml"
|
211
|
+
- ".vscode/settings.json"
|
211
212
|
- APACHE-LICENSE-2.0
|
212
213
|
- CHANGELOG.md
|
214
|
+
- Gemfile
|
213
215
|
- MIT-LICENSE
|
214
216
|
- NOTICE
|
215
217
|
- PROPOSAL_FOR_RESPONSE_DESCRIPTIONS.md
|
@@ -258,12 +260,7 @@ files:
|
|
258
260
|
- config/locales/tr.yml
|
259
261
|
- config/locales/zh-CN.yml
|
260
262
|
- config/locales/zh-TW.yml
|
261
|
-
- gemfiles/Gemfile.
|
262
|
-
- gemfiles/Gemfile.rails51
|
263
|
-
- gemfiles/Gemfile.rails52
|
264
|
-
- gemfiles/Gemfile.rails60
|
265
|
-
- gemfiles/Gemfile.rails61
|
266
|
-
- gemfiles/Gemfile.rails70
|
263
|
+
- gemfiles/Gemfile.tools
|
267
264
|
- images/screenshot-1.png
|
268
265
|
- images/screenshot-2.png
|
269
266
|
- lib/apipie-rails.rb
|
@@ -342,7 +339,9 @@ files:
|
|
342
339
|
- rel-eng/tito.props
|
343
340
|
- spec/controllers/api/v1/architectures_controller_spec.rb
|
344
341
|
- spec/controllers/api/v2/architectures_controller_spec.rb
|
342
|
+
- spec/controllers/api/v2/empty_middle_controller_spec.rb
|
345
343
|
- spec/controllers/api/v2/nested/resources_controller_spec.rb
|
344
|
+
- spec/controllers/api/v2/sub/footguns_controller_spec.rb
|
346
345
|
- spec/controllers/concerns_controller_spec.rb
|
347
346
|
- spec/controllers/extended_controller_spec.rb
|
348
347
|
- spec/controllers/included_param_group_controller_spec.rb
|
@@ -354,8 +353,10 @@ files:
|
|
354
353
|
- spec/dummy/app/controllers/api/v1/base_controller.rb
|
355
354
|
- spec/dummy/app/controllers/api/v2/architectures_controller.rb
|
356
355
|
- spec/dummy/app/controllers/api/v2/base_controller.rb
|
356
|
+
- spec/dummy/app/controllers/api/v2/empty_middle_controller.rb
|
357
357
|
- spec/dummy/app/controllers/api/v2/nested/architectures_controller.rb
|
358
358
|
- spec/dummy/app/controllers/api/v2/nested/resources_controller.rb
|
359
|
+
- spec/dummy/app/controllers/api/v2/sub/footguns_controller.rb
|
359
360
|
- spec/dummy/app/controllers/application_controller.rb
|
360
361
|
- spec/dummy/app/controllers/concerns_controller.rb
|
361
362
|
- spec/dummy/app/controllers/extended_controller.rb
|
@@ -408,6 +409,7 @@ files:
|
|
408
409
|
- spec/lib/apipie/apipies_controller_spec.rb
|
409
410
|
- spec/lib/apipie/application_spec.rb
|
410
411
|
- spec/lib/apipie/configuration_spec.rb
|
412
|
+
- spec/lib/apipie/extractor/collector_spec.rb
|
411
413
|
- spec/lib/apipie/extractor/recorder/middleware_spec.rb
|
412
414
|
- spec/lib/apipie/extractor/recorder_spec.rb
|
413
415
|
- spec/lib/apipie/extractor/writer_spec.rb
|
@@ -470,7 +472,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
470
472
|
- !ruby/object:Gem::Version
|
471
473
|
version: '0'
|
472
474
|
requirements: []
|
473
|
-
rubygems_version: 3.
|
475
|
+
rubygems_version: 3.4.11
|
474
476
|
signing_key:
|
475
477
|
specification_version: 4
|
476
478
|
summary: Rails REST API documentation tool
|
data/gemfiles/Gemfile.rails50
DELETED
@@ -1,10 +0,0 @@
|
|
1
|
-
source "https://rubygems.org"
|
2
|
-
|
3
|
-
gemspec path: '..'
|
4
|
-
|
5
|
-
gem 'actionpack', '~> 5.0.0'
|
6
|
-
gem 'activesupport', '~> 5.0.0'
|
7
|
-
gem 'mime-types', '~> 2.99.3'
|
8
|
-
gem 'rails-controller-testing'
|
9
|
-
|
10
|
-
gem 'test_engine', path: '../spec/dummy/components/test_engine', group: :test
|