Skip to content

Commit 6244ff8

Browse files
committed
Fix infinite loop when mounting endpoint with same superclass
Subclass APIs were being assigned the same top level inheritable settings from the superclass. When an API attempted to mount another API with the same superclass, the same setting object would be added to the setting stack. When an attempt was made to retrieve a value from the settings, it would sit in loop calling itself.
1 parent 74e21ab commit 6244ff8

File tree

4 files changed

+18
-7
lines changed

4 files changed

+18
-7
lines changed

.rubocop_todo.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ Metrics/AbcSize:
3434
# Offense count: 282
3535
# Configuration parameters: CountComments, ExcludedMethods.
3636
Metrics/BlockLength:
37-
Max: 3117
37+
Max: 3125
3838

3939
# Offense count: 9
4040
# Configuration parameters: CountComments.

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
* [#1724](https://github.com/ruby-grape/grape/pull/1724): Optional nested array validation - [@ericproulx](https://github.com/ericproulx).
1515
* [#1725](https://github.com/ruby-grape/grape/pull/1725): Fix `rescue_from :all` documentation - [@Jelkster](https://github.com/Jelkster).
1616
* [#1726](https://github.com/ruby-grape/grape/pull/1726): Improved startup performance during API method generation - [@jkowens](https://github.com/jkowens).
17+
* [#1727](https://github.com/ruby-grape/grape/pull/1727): Fix infinite loop when mounting endpoint with same superclass - [@jkowens](https://github.com/jkowens).
1718
* Your contribution here.
1819

1920
### 1.0.1 (9/8/2017)

lib/grape/dsl/settings.rb

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -165,13 +165,13 @@ def within_namespace(&_block)
165165

166166
private
167167

168-
# Builds the current class :inheritable_setting. If available, it returns the superclass's :inheritable_setting.
169-
# Otherwise, a clean :inheritable_setting is returned.
168+
# Builds the current class :inheritable_setting. If available, it inherits from
169+
# the superclass's :inheritable_setting.
170170
def build_top_level_setting
171-
if defined?(superclass) && superclass.respond_to?(:inheritable_setting) && superclass != Grape::API
172-
superclass.inheritable_setting
173-
else
174-
Grape::Util::InheritableSetting.new
171+
Grape::Util::InheritableSetting.new.tap do |setting|
172+
if defined?(superclass) && superclass.respond_to?(:inheritable_setting) && superclass != Grape::API
173+
setting.inherit_from superclass.inheritable_setting
174+
end
175175
end
176176
end
177177
end

spec/grape/api_spec.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3129,6 +3129,16 @@ def static
31293129
get '/two/v1/world'
31303130
expect(last_response.status).to eq 200
31313131
end
3132+
3133+
context 'when mounting class extends a subclass of Grape::API' do
3134+
it 'mounts APIs with the same superclass' do
3135+
base_api = Class.new(Grape::API)
3136+
a = Class.new(base_api)
3137+
b = Class.new(base_api)
3138+
3139+
expect { a.mount b }.to_not raise_error
3140+
end
3141+
end
31323142
end
31333143
end
31343144

0 commit comments

Comments
 (0)