Skip to content

Commit 094af45

Browse files
bf4Yohan Robert
authored and
Yohan Robert
committed
Prevent controller options from being mutated
- The controller options are now frozen - The serialization_context is now passed to the adapter via the adapter options and no more via as_json
1 parent 61412d8 commit 094af45

File tree

8 files changed

+225
-275
lines changed

8 files changed

+225
-275
lines changed

lib/action_controller/serialization.rb

+11-6
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,13 @@ def serialization_scope
2626
respond_to?(_serialization_scope, true)
2727
end
2828

29-
def get_serializer(resource, options = {})
29+
def get_serializer(resource, serialization_options = {})
3030
if !use_adapter?
3131
warn 'ActionController::Serialization#use_adapter? has been removed. '\
3232
"Please pass 'adapter: false' or see ActiveSupport::SerializableResource.new"
33-
options[:adapter] = false
33+
serialization_options[:adapter] = false
3434
end
35-
serializable_resource = ActiveModel::SerializableResource.new(resource, options)
35+
serializable_resource = ActiveModel::SerializableResource.new(resource, serialization_options)
3636
if serializable_resource.serializer?
3737
serializable_resource.serialization_scope ||= serialization_scope
3838
serializable_resource.serialization_scope_name = _serialization_scope
@@ -56,10 +56,15 @@ def use_adapter?
5656

5757
[:_render_option_json, :_render_with_renderer_json].each do |renderer_method|
5858
define_method renderer_method do |resource, options|
59-
options.fetch(:serialization_context) do
60-
options[:serialization_context] = ActiveModelSerializers::SerializationContext.new(request, options)
59+
options.freeze
60+
serialization_options = options.deep_dup
61+
if options.key?(:serializer)
62+
serialization_options[:serializer] = options[:serializer]
6163
end
62-
serializable_resource = get_serializer(resource, options)
64+
unless serialization_options.key?(:serialization_context)
65+
serialization_options[:serialization_context] = ActiveModelSerializers::SerializationContext.new(request, serialization_options)
66+
end
67+
serializable_resource = get_serializer(resource, serialization_options)
6368
super(serializable_resource, options)
6469
end
6570
end

lib/active_model/serializable_resource.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
require 'active_model_serializers/adapter'
33
module ActiveModel
44
class SerializableResource
5-
ADAPTER_OPTION_KEYS = Set.new([:include, :fields, :adapter, :meta, :meta_key, :links])
5+
ADAPTER_OPTION_KEYS = Set.new([:include, :fields, :adapter, :meta, :meta_key, :links, :serialization_context])
66
include ActiveModelSerializers::Logging
77

88
delegate :serializable_hash, :as_json, :to_json, to: :adapter

lib/active_model_serializers/adapter/json.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ class Json < Base
44
def serializable_hash(options = nil)
55
options ||= {}
66
serialized_hash = { root => Attributes.new(serializer, instance_options).serializable_hash(options) }
7-
transform_key_casing!(serialized_hash, options[:serialization_context])
7+
transform_key_casing!(serialized_hash, instance_options[:serialization_context])
88
end
99
end
1010
end

lib/active_model_serializers/adapter/json_api.rb

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# coding: utf-8
12
# {http://jsonapi.org/format/ JSON API specification}
23
# rubocop:disable Style/AsciiComments
34
# TODO: implement!
@@ -43,14 +44,13 @@ def default_key_transform
4344

4445
# {http://jsonapi.org/format/#crud Requests are transactional, i.e. success or failure}
4546
# {http://jsonapi.org/format/#document-top-level data and errors MUST NOT coexist in the same document.}
46-
def serializable_hash(options = nil)
47-
options ||= {}
47+
def serializable_hash(_options = nil)
4848
document = if serializer.success?
49-
success_document(options)
49+
success_document
5050
else
5151
failure_document
5252
end
53-
transform_key_casing!(document, options[:serialization_context])
53+
transform_key_casing!(document, instance_options[:serialization_context])
5454
end
5555

5656
# {http://jsonapi.org/format/#document-top-level Primary data}
@@ -68,7 +68,7 @@ def serializable_hash(options = nil)
6868
# links: toplevel_links,
6969
# jsonapi: toplevel_jsonapi
7070
# }.reject! {|_,v| v.nil? }
71-
def success_document(options)
71+
def success_document
7272
is_collection = serializer.respond_to?(:each)
7373
serializers = is_collection ? serializer : [serializer]
7474
primary_data, included = resource_objects_for(serializers)
@@ -128,7 +128,7 @@ def success_document(options)
128128

129129
if is_collection && serializer.paginated?
130130
hash[:links] ||= {}
131-
hash[:links].update(pagination_links_for(serializer, options))
131+
hash[:links].update(pagination_links_for(serializer))
132132
end
133133

134134
hash
@@ -498,8 +498,8 @@ def links_for(serializer)
498498
# end
499499
# prs:
500500
# https://github.com/rails-api/active_model_serializers/pull/1041
501-
def pagination_links_for(serializer, options)
502-
PaginationLinks.new(serializer.object, options[:serialization_context]).serializable_hash(options)
501+
def pagination_links_for(serializer)
502+
PaginationLinks.new(serializer.object, instance_options[:serialization_context]).as_json(instance_options)
503503
end
504504

505505
# {http://jsonapi.org/format/#document-meta Docment Meta}

lib/active_model_serializers/adapter/json_api/pagination_links.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ def initialize(collection, context)
1111
@context = context
1212
end
1313

14-
def serializable_hash(options = {})
14+
def as_json(options = {})
1515
per_page = collection.try(:per_page) || collection.try(:limit_value) || collection.size
1616
pages_from.each_with_object({}) do |(key, value), hash|
1717
params = query_parameters.merge(page: { number: value, size: per_page }).to_query

test/adapter/json/key_case_test.rb

+13-10
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,19 @@ class PostSerializer < ActiveModel::Serializer
2121
def setup
2222
ActionController::Base.cache_store.clear
2323
@blog = Blog.new(id: 1, name: 'My Blog!!', special_attribute: 'neat')
24-
serializer = CustomBlogSerializer.new(@blog)
25-
@adapter = ActiveModelSerializers::Adapter::Json.new(serializer)
2624
end
2725

2826
def test_key_transform_default
2927
mock_request
3028
assert_equal({
3129
blog: { id: 1, special_attribute: 'neat', articles: nil }
32-
}, @adapter.serializable_hash(@options))
30+
}, adapter.serializable_hash)
3331
end
3432

3533
def test_key_transform_global_config
3634
mock_request
3735
result = with_config(key_transform: :camel_lower) do
38-
@adapter.serializable_hash(@options)
36+
adapter.serializable_hash
3937
end
4038
assert_equal({
4139
blog: { id: 1, specialAttribute: 'neat', articles: nil }
@@ -45,7 +43,7 @@ def test_key_transform_global_config
4543
def test_key_transform_serialization_ctx_overrides_global_config
4644
mock_request(:camel)
4745
result = with_config(key_transform: :camel_lower) do
48-
@adapter.serializable_hash(@options)
46+
adapter.serializable_hash
4947
end
5048
assert_equal({
5149
Blog: { Id: 1, SpecialAttribute: 'neat', Articles: nil }
@@ -56,36 +54,41 @@ def test_key_transform_undefined
5654
mock_request(:blam)
5755
result = nil
5856
assert_raises NoMethodError do
59-
result = @adapter.serializable_hash(@options)
57+
result = adapter.serializable_hash
6058
end
6159
end
6260

6361
def test_key_transform_dashed
6462
mock_request(:dashed)
6563
assert_equal({
6664
blog: { id: 1, :"special-attribute" => 'neat', articles: nil }
67-
}, @adapter.serializable_hash(@options))
65+
}, adapter.serializable_hash)
6866
end
6967

7068
def test_key_transform_unaltered
7169
mock_request(:unaltered)
7270
assert_equal({
7371
blog: { id: 1, special_attribute: 'neat', articles: nil }
74-
}, @adapter.serializable_hash(@options))
72+
}, adapter.serializable_hash)
7573
end
7674

7775
def test_key_transform_camel
7876
mock_request(:camel)
7977
assert_equal({
8078
Blog: { Id: 1, SpecialAttribute: 'neat', Articles: nil }
81-
}, @adapter.serializable_hash(@options))
79+
}, adapter.serializable_hash)
8280
end
8381

8482
def test_key_transform_camel_lower
8583
mock_request(:camel_lower)
8684
assert_equal({
8785
blog: { id: 1, specialAttribute: 'neat', articles: nil }
88-
}, @adapter.serializable_hash(@options))
86+
}, adapter.serializable_hash)
87+
end
88+
89+
def adapter
90+
serializer = CustomBlogSerializer.new(@blog)
91+
ActiveModelSerializers::Adapter::Json.new(serializer, @options || {})
8992
end
9093
end
9194
end

0 commit comments

Comments
 (0)