Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit f107b18

Browse files
committedOct 25, 2019
add allow_wildcard configuration
1 parent 5ce94fd commit f107b18

File tree

7 files changed

+114
-4
lines changed

7 files changed

+114
-4
lines changed
 

‎CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ Breaking changes:
66

77
Features:
88

9+
- [#2362](https://github.com/rails-api/active_model_serializers/pull/2362) Add `allow_wildcard` configuration option (@Borzik)
10+
911
Fixes:
1012

1113
- [#2344](https://github.com/rails-api/active_model_serializers/pull/2344) Fixes #2341 introduced since #2223 (@wasifhossain)

‎docs/general/configuration_options.md

+12
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,18 @@ What relationships to serialize by default. Default: `'*'`, which includes one
6262
objects. See [includes](adapters.md#included) for more info.
6363

6464

65+
##### allow_wildcard
66+
67+
Enable wildcard `include` directives (`*`, `**`).
68+
69+
Possible values:
70+
71+
- `true` (default)
72+
- `false`
73+
74+
When `false`, nested associations to be included must be explicitly specified. Note: this will override default_includes configuration as `*` include will no longer be accepted.
75+
76+
6577
##### serializer_lookup_chain
6678

6779
Configures how serializers are searched for. By default, the lookup chain is

‎lib/active_model/serializer.rb

+2-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ def self.include_directive_from_options(options)
106106
if options[:include_directive]
107107
options[:include_directive]
108108
elsif options[:include]
109-
JSONAPI::IncludeDirective.new(options[:include], allow_wildcard: true)
109+
JSONAPI::IncludeDirective.new(options[:include], allow_wildcard: config.allow_wildcard)
110110
else
111111
ActiveModelSerializers.default_include_directive
112112
end
@@ -135,6 +135,7 @@ def config.array_serializer
135135
end
136136

137137
config.default_includes = '*'
138+
config.allow_wildcard = true
138139
config.adapter = :attributes
139140
config.key_transform = nil
140141
config.jsonapi_pagination_links_enabled = true

‎lib/active_model_serializers.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def self.location_of_caller
4040
# Memoized default include directive
4141
# @return [JSONAPI::IncludeDirective]
4242
def self.default_include_directive
43-
@default_include_directive ||= JSONAPI::IncludeDirective.new(config.default_includes, allow_wildcard: true)
43+
@default_include_directive ||= JSONAPI::IncludeDirective.new(config.default_includes, allow_wildcard: config.allow_wildcard)
4444
end
4545

4646
def self.silence_warnings

‎lib/active_model_serializers/adapter/json_api.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def self.fragment_cache(cached_hash, non_cached_hash, root = true)
5252

5353
def initialize(serializer, options = {})
5454
super
55-
@include_directive = JSONAPI::IncludeDirective.new(options[:include], allow_wildcard: true)
55+
@include_directive = JSONAPI::IncludeDirective.new(options[:include], allow_wildcard: ActiveModelSerializers.config.allow_wildcard)
5656
@fieldset = options[:fieldset] || ActiveModel::Serializer::Fieldset.new(options.delete(:fields))
5757
end
5858

@@ -452,7 +452,7 @@ def data_for(serializer, include_slice)
452452
def relationships_for(serializer, requested_associations, include_slice)
453453
include_directive = JSONAPI::IncludeDirective.new(
454454
requested_associations,
455-
allow_wildcard: true
455+
allow_wildcard: ActiveModelSerializers.config.allow_wildcard
456456
)
457457
serializer.associations(include_directive, include_slice).each_with_object({}) do |association, hash|
458458
hash[association.key] = Relationship.new(serializer, instance_options, association).as_json

‎test/action_controller/json/include_test.rb

+78
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ class IncludeTest < ActionController::TestCase
99
INCLUDE_STRING = 'posts.comments'.freeze
1010
INCLUDE_HASH = { posts: :comments }.freeze
1111
DEEP_INCLUDE = 'posts.comments.author'.freeze
12+
WILDCARD_INCLUDE = '*'.freeze
13+
DEEP_WILDCARD_INCLUDE = '**'.freeze
1214

1315
class IncludeTestController < ActionController::Base
1416
def setup_data
@@ -57,6 +59,16 @@ def render_resource_with_deep_include
5759
render json: @author, include: DEEP_INCLUDE, adapter: :json
5860
end
5961

62+
def render_resource_with_wildcard_include
63+
setup_data
64+
render json: @author, include: WILDCARD_INCLUDE, adapter: :json
65+
end
66+
67+
def render_resource_with_deep_wildcard_include
68+
setup_data
69+
render json: @author, include: DEEP_WILDCARD_INCLUDE, adapter: :json
70+
end
71+
6072
def render_without_recursive_relationships
6173
# testing recursive includes ('**') can't have any cycles in the
6274
# relationships, or we enter an infinite loop.
@@ -114,6 +126,48 @@ def test_render_resource_with_deep_include
114126
assert_equal(expected_deep_include_response, response)
115127
end
116128

129+
def test_render_resource_with_wildcard_include
130+
get :render_resource_with_wildcard_include
131+
132+
response = JSON.parse(@response.body)
133+
134+
assert_equal(expected_wildcard_include_response, response)
135+
end
136+
137+
def test_render_resource_with_wildcard_include_with_wildcards_disabled
138+
with_wildcards_disabled do
139+
get :render_resource_with_wildcard_include
140+
end
141+
142+
expected = {
143+
'author' => {
144+
'id' => 1,
145+
'name' => 'Steve K.'
146+
}
147+
}
148+
149+
response = JSON.parse(@response.body)
150+
151+
assert_equal(expected, response)
152+
end
153+
154+
def test_render_resource_with_deep_wildcard_include_with_wildcards_disabled
155+
with_wildcards_disabled do
156+
get :render_resource_with_deep_wildcard_include
157+
end
158+
159+
expected = {
160+
'author' => {
161+
'id' => 1,
162+
'name' => 'Steve K.'
163+
}
164+
}
165+
166+
response = JSON.parse(@response.body)
167+
168+
assert_equal(expected, response)
169+
end
170+
117171
def test_render_with_empty_default_includes
118172
with_default_includes '' do
119173
get :render_without_include
@@ -176,6 +230,22 @@ def test_render_with_includes_overrides_default_includes
176230

177231
private
178232

233+
def expected_wildcard_include_response
234+
{
235+
'author' => {
236+
'id' => 1,
237+
'name' => 'Steve K.',
238+
'posts' => [
239+
{
240+
'id' => 42, 'title' => 'New Post', 'body' => 'Body'
241+
}
242+
],
243+
'roles' => [],
244+
'bio' => {}
245+
}
246+
}
247+
end
248+
179249
def expected_include_response
180250
{
181251
'author' => {
@@ -238,6 +308,14 @@ def with_default_includes(include_directive)
238308
clear_include_directive_cache
239309
end
240310

311+
def with_wildcards_disabled
312+
original = ActiveModelSerializers.config.allow_wildcard
313+
ActiveModelSerializers.config.allow_wildcard = false
314+
yield
315+
ensure
316+
ActiveModelSerializers.config.allow_wildcard = original
317+
end
318+
241319
def clear_include_directive_cache
242320
ActiveModelSerializers
243321
.instance_variable_set(:@default_include_directive, nil)

‎test/action_controller/json_api/linked_test.rb

+17
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,23 @@ def test_render_resource_with_nested_has_many_include
150150
assert_equal expected_linked, response['included']
151151
end
152152

153+
def test_render_resource_with_nested_has_many_include_with_wildcards_disabled
154+
ActiveModel::Serializer.config.allow_wildcard = false
155+
get '/render_resource_with_nested_has_many_include_wildcard'
156+
ActiveModel::Serializer.config.allow_wildcard = true
157+
response = JSON.parse(@response.body)
158+
expected_linked = [
159+
{
160+
'id' => '1',
161+
'type' => 'authors',
162+
'attributes' => {
163+
'name' => 'Steve K.'
164+
}
165+
}
166+
]
167+
assert_equal expected_linked, response['included']
168+
end
169+
153170
def test_render_resource_with_include_of_custom_key_by_original
154171
get '/render_resource_with_include_of_custom_key_by_original'
155172
response = JSON.parse(@response.body)

0 commit comments

Comments
 (0)
Please sign in to comment.