Skip to content

Commit 2c4d574

Browse files
pablogomez0dblock
authored andcommitted
Make helpers available in subclasses (#1665)
* Make helpers available in subclasses Updating settings code to define :top_level_setting with parent's :inheritable_setting when available. This will emulate inheritance, with its expected capabilities (sharing and overriding). * Update CHANGELOG accordingly * Change method name according to review
1 parent a284f24 commit 2c4d574

File tree

3 files changed

+129
-2
lines changed

3 files changed

+129
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
* Your contribution here.
66
* [#1652](https://github.com/ruby-grape/grape/pull/1652): Add the original exception to the error_formatter the original exception - [@dcsg](https://github.com/dcsg).
7+
* [#1665](https://github.com/ruby-grape/grape/pull/1665): Make helpers available in subclasses - [@pablonahuelgomez](https://github.com/pablonahuelgomez).
78

89
#### Fixes
910

lib/grape/dsl/settings.rb

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
module Grape
44
module DSL
5-
# Keeps track of settings (impemented as key-value pairs, grouped by
5+
# Keeps track of settings (implemented as key-value pairs, grouped by
66
# types), in two contexts: top-level settings which apply globally no
77
# matter where they're defined, and inheritable settings which apply only
88
# in the current scope and scopes nested under it.
@@ -13,7 +13,7 @@ module Settings
1313

1414
# Fetch our top-level settings, which apply to all endpoints in the API.
1515
def top_level_setting
16-
@top_level_setting ||= Grape::Util::InheritableSetting.new
16+
@top_level_setting ||= build_top_level_setting
1717
end
1818

1919
# Fetch our current inheritable settings, which are inherited by
@@ -162,6 +162,18 @@ def within_namespace(&_block)
162162

163163
result
164164
end
165+
166+
private
167+
168+
# Builds the current class :inheritable_setting. If available, it returns the superclass's :inheritable_setting.
169+
# Otherwise, a clean :inheritable_setting is returned.
170+
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
175+
end
176+
end
165177
end
166178
end
167179
end
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
require 'spec_helper'
2+
3+
describe Grape::API::Helpers do
4+
let(:user) { 'Miguel Caneo' }
5+
let(:id) { '42' }
6+
7+
module InheritedHelpersSpec
8+
class SuperClass < Grape::API
9+
helpers do
10+
params(:superclass_params) { requires :id, type: String }
11+
12+
def current_user
13+
params[:user]
14+
end
15+
end
16+
end
17+
18+
class OverriddenSubClass < SuperClass
19+
params { use :superclass_params }
20+
21+
helpers do
22+
def current_user
23+
"#{params[:user]} with id"
24+
end
25+
end
26+
27+
get 'resource' do
28+
"#{current_user}: #{params['id']}"
29+
end
30+
end
31+
32+
class SubClass < SuperClass
33+
params { use :superclass_params }
34+
35+
get 'resource' do
36+
"#{current_user}: #{params['id']}"
37+
end
38+
end
39+
40+
class Example < SubClass
41+
params { use :superclass_params }
42+
43+
get 'resource' do
44+
"#{current_user}: #{params['id']}"
45+
end
46+
end
47+
end
48+
49+
context 'non overriding subclass' do
50+
subject { InheritedHelpersSpec::SubClass }
51+
52+
def app
53+
subject
54+
end
55+
56+
context 'given expected params' do
57+
it 'inherits helpers from a superclass' do
58+
get '/resource', id: id, user: user
59+
expect(last_response.body).to eq("#{user}: #{id}")
60+
end
61+
end
62+
63+
context 'with lack of expected params' do
64+
it 'returns missing error' do
65+
get '/resource'
66+
expect(last_response.body).to eq('id is missing')
67+
end
68+
end
69+
end
70+
71+
context 'overriding subclass' do
72+
subject { InheritedHelpersSpec::OverriddenSubClass }
73+
74+
def app
75+
subject
76+
end
77+
78+
context 'given expected params' do
79+
it 'overrides helpers from a superclass' do
80+
get '/resource', id: id, user: user
81+
expect(last_response.body).to eq("#{user} with id: #{id}")
82+
end
83+
end
84+
85+
context 'with lack of expected params' do
86+
it 'returns missing error' do
87+
get '/resource'
88+
expect(last_response.body).to eq('id is missing')
89+
end
90+
end
91+
end
92+
93+
context 'example subclass' do
94+
subject { InheritedHelpersSpec::Example }
95+
96+
def app
97+
subject
98+
end
99+
100+
context 'given expected params' do
101+
it 'inherits helpers from a superclass' do
102+
get '/resource', id: id, user: user
103+
expect(last_response.body).to eq("#{user}: #{id}")
104+
end
105+
end
106+
107+
context 'with lack of expected params' do
108+
it 'returns missing error' do
109+
get '/resource'
110+
expect(last_response.body).to eq('id is missing')
111+
end
112+
end
113+
end
114+
end

0 commit comments

Comments
 (0)