active_model_serializers 0.10.0 → 0.10.2
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/.rubocop.yml +2 -4
- data/.travis.yml +1 -0
- data/CHANGELOG.md +39 -2
- data/Gemfile +1 -1
- data/README.md +21 -24
- data/Rakefile +3 -3
- data/active_model_serializers.gemspec +19 -23
- data/docs/general/adapters.md +4 -2
- data/docs/general/configuration_options.md +6 -1
- data/docs/general/deserialization.md +1 -1
- data/docs/general/fields.md +31 -0
- data/docs/general/rendering.md +7 -2
- data/docs/general/serializers.md +62 -3
- data/docs/howto/add_pagination_links.md +2 -3
- data/docs/integrations/ember-and-json-api.md +25 -10
- data/docs/jsonapi/schema.md +1 -1
- data/lib/action_controller/serialization.rb +4 -3
- data/lib/active_model/serializer/adapter/base.rb +2 -0
- data/lib/active_model/serializer/array_serializer.rb +8 -5
- data/lib/active_model/serializer/associations.rb +6 -7
- data/lib/active_model/serializer/belongs_to_reflection.rb +0 -3
- data/lib/active_model/serializer/caching.rb +67 -112
- data/lib/active_model/serializer/collection_serializer.rb +30 -10
- data/lib/active_model/serializer/configuration.rb +1 -0
- data/lib/active_model/serializer/error_serializer.rb +11 -7
- data/lib/active_model/serializer/errors_serializer.rb +25 -20
- data/lib/active_model/serializer/has_many_reflection.rb +0 -3
- data/lib/active_model/serializer/has_one_reflection.rb +0 -3
- data/lib/active_model/serializer/lint.rb +134 -130
- data/lib/active_model/serializer/reflection.rb +3 -3
- data/lib/active_model/serializer/version.rb +1 -1
- data/lib/active_model/serializer.rb +57 -15
- data/lib/active_model_serializers/adapter/attributes.rb +2 -67
- data/lib/active_model_serializers/adapter/base.rb +38 -38
- data/lib/active_model_serializers/adapter/json_api/link.rb +1 -1
- data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +8 -1
- data/lib/active_model_serializers/adapter/json_api.rb +36 -28
- data/lib/active_model_serializers/adapter.rb +6 -0
- data/lib/active_model_serializers/deprecate.rb +1 -2
- data/lib/active_model_serializers/deserialization.rb +2 -0
- data/lib/active_model_serializers/model.rb +3 -1
- data/lib/active_model_serializers/railtie.rb +3 -1
- data/lib/active_model_serializers/register_jsonapi_renderer.rb +44 -31
- data/lib/active_model_serializers/serialization_context.rb +10 -3
- data/lib/active_model_serializers.rb +6 -0
- data/lib/generators/rails/serializer_generator.rb +3 -3
- data/lib/grape/active_model_serializers.rb +7 -5
- data/lib/grape/formatters/active_model_serializers.rb +19 -2
- data/lib/grape/helpers/active_model_serializers.rb +1 -0
- data/test/action_controller/adapter_selector_test.rb +4 -4
- data/test/action_controller/explicit_serializer_test.rb +5 -4
- data/test/action_controller/json/include_test.rb +106 -27
- data/test/action_controller/json_api/errors_test.rb +6 -7
- data/test/action_controller/json_api/linked_test.rb +29 -24
- data/test/action_controller/json_api/pagination_test.rb +19 -19
- data/test/action_controller/serialization_test.rb +10 -7
- data/test/active_model_serializers/json_pointer_test.rb +15 -13
- data/test/active_model_serializers/key_transform_test.rb +254 -252
- data/test/active_model_serializers/model_test.rb +6 -4
- data/test/active_model_serializers/register_jsonapi_renderer_test_isolated.rb +143 -0
- data/test/active_model_serializers/serialization_context_test_isolated.rb +23 -10
- data/test/adapter/json/collection_test.rb +14 -0
- data/test/adapter/json/transform_test.rb +14 -14
- data/test/adapter/json_api/collection_test.rb +4 -3
- data/test/adapter/json_api/errors_test.rb +17 -19
- data/test/adapter/json_api/has_many_test.rb +18 -18
- data/test/adapter/json_api/json_api_test.rb +5 -7
- data/test/adapter/json_api/linked_test.rb +9 -6
- data/test/adapter/json_api/links_test.rb +3 -1
- data/test/adapter/json_api/pagination_links_test.rb +19 -7
- data/test/adapter/json_api/relationships_test.rb +9 -4
- data/test/adapter/json_api/resource_identifier_test.rb +7 -2
- data/test/adapter/json_api/resource_meta_test.rb +3 -3
- data/test/adapter/json_api/transform_test.rb +251 -250
- data/test/adapter/json_api/type_test.rb +1 -1
- data/test/adapter/json_test.rb +8 -7
- data/test/adapter/null_test.rb +1 -2
- data/test/adapter/polymorphic_test.rb +5 -5
- data/test/adapter_test.rb +1 -1
- data/test/benchmark/app.rb +1 -1
- data/test/benchmark/bm_caching.rb +15 -15
- data/test/benchmark/bm_transform.rb +16 -5
- data/test/benchmark/controllers.rb +16 -17
- data/test/benchmark/fixtures.rb +72 -72
- data/test/cache_test.rb +101 -45
- data/test/collection_serializer_test.rb +2 -2
- data/test/fixtures/poro.rb +8 -7
- data/test/grape_test.rb +152 -56
- data/test/lint_test.rb +1 -1
- data/test/logger_test.rb +13 -11
- data/test/serializable_resource_test.rb +18 -22
- data/test/serializers/associations_test.rb +10 -10
- data/test/serializers/attribute_test.rb +1 -1
- data/test/serializers/attributes_test.rb +1 -1
- data/test/serializers/fieldset_test.rb +1 -1
- data/test/serializers/meta_test.rb +12 -6
- data/test/serializers/root_test.rb +1 -1
- data/test/serializers/serializer_for_test.rb +3 -1
- data/test/support/isolated_unit.rb +5 -2
- data/test/support/rails5_shims.rb +8 -2
- data/test/support/rails_app.rb +0 -9
- data/test/support/serialization_testing.rb +7 -5
- metadata +54 -24
- data/.rubocop_todo.yml +0 -167
- data/lib/active_model/serializer/include_tree.rb +0 -111
- data/test/include_tree/from_include_args_test.rb +0 -26
- data/test/include_tree/from_string_test.rb +0 -94
- data/test/include_tree/include_args_to_hash_test.rb +0 -64
@@ -1,146 +1,150 @@
|
|
1
|
-
module ActiveModel
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
1
|
+
module ActiveModel
|
2
|
+
class Serializer
|
3
|
+
module Lint
|
4
|
+
# == Active \Model \Serializer \Lint \Tests
|
5
|
+
#
|
6
|
+
# You can test whether an object is compliant with the Active \Model \Serializers
|
7
|
+
# API by including <tt>ActiveModel::Serializer::Lint::Tests</tt> in your TestCase.
|
8
|
+
# It will include tests that tell you whether your object is fully compliant,
|
9
|
+
# or if not, which aspects of the API are not implemented.
|
10
|
+
#
|
11
|
+
# Note an object is not required to implement all APIs in order to work
|
12
|
+
# with Active \Model \Serializers. This module only intends to provide guidance in case
|
13
|
+
# you want all features out of the box.
|
14
|
+
#
|
15
|
+
# These tests do not attempt to determine the semantic correctness of the
|
16
|
+
# returned values. For instance, you could implement <tt>serializable_hash</tt> to
|
17
|
+
# always return +{}+, and the tests would pass. It is up to you to ensure
|
18
|
+
# that the values are semantically meaningful.
|
19
|
+
module Tests
|
20
|
+
# Passes if the object responds to <tt>serializable_hash</tt> and if it takes
|
21
|
+
# zero or one arguments.
|
22
|
+
# Fails otherwise.
|
23
|
+
#
|
24
|
+
# <tt>serializable_hash</tt> returns a hash representation of a object's attributes.
|
25
|
+
# Typically, it is implemented by including ActiveModel::Serialization.
|
26
|
+
def test_serializable_hash
|
27
|
+
assert_respond_to resource, :serializable_hash, 'The resource should respond to serializable_hash'
|
28
|
+
resource.serializable_hash
|
29
|
+
resource.serializable_hash(nil)
|
30
|
+
end
|
29
31
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
32
|
+
# Passes if the object responds to <tt>read_attribute_for_serialization</tt>
|
33
|
+
# and if it requires one argument (the attribute to be read).
|
34
|
+
# Fails otherwise.
|
35
|
+
#
|
36
|
+
# <tt>read_attribute_for_serialization</tt> gets the attribute value for serialization
|
37
|
+
# Typically, it is implemented by including ActiveModel::Serialization.
|
38
|
+
def test_read_attribute_for_serialization
|
39
|
+
assert_respond_to resource, :read_attribute_for_serialization, 'The resource should respond to read_attribute_for_serialization'
|
40
|
+
actual_arity = resource.method(:read_attribute_for_serialization).arity
|
41
|
+
# using absolute value since arity is:
|
42
|
+
# 1 for def read_attribute_for_serialization(name); end
|
43
|
+
# -1 for alias :read_attribute_for_serialization :send
|
44
|
+
assert_equal 1, actual_arity.abs, "expected #{actual_arity.inspect}.abs to be 1 or -1"
|
45
|
+
end
|
44
46
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
47
|
+
# Passes if the object responds to <tt>as_json</tt> and if it takes
|
48
|
+
# zero or one arguments.
|
49
|
+
# Fails otherwise.
|
50
|
+
#
|
51
|
+
# <tt>as_json</tt> returns a hash representation of a serialized object.
|
52
|
+
# It may delegate to <tt>serializable_hash</tt>
|
53
|
+
# Typically, it is implemented either by including ActiveModel::Serialization
|
54
|
+
# which includes ActiveModel::Serializers::JSON.
|
55
|
+
# or by the JSON gem when required.
|
56
|
+
def test_as_json
|
57
|
+
assert_respond_to resource, :as_json
|
58
|
+
resource.as_json
|
59
|
+
resource.as_json(nil)
|
60
|
+
end
|
59
61
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
62
|
+
# Passes if the object responds to <tt>to_json</tt> and if it takes
|
63
|
+
# zero or one arguments.
|
64
|
+
# Fails otherwise.
|
65
|
+
#
|
66
|
+
# <tt>to_json</tt> returns a string representation (JSON) of a serialized object.
|
67
|
+
# It may be called on the result of <tt>as_json</tt>.
|
68
|
+
# Typically, it is implemented on all objects when the JSON gem is required.
|
69
|
+
def test_to_json
|
70
|
+
assert_respond_to resource, :to_json
|
71
|
+
resource.to_json
|
72
|
+
resource.to_json(nil)
|
73
|
+
end
|
72
74
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
75
|
+
# Passes if the object responds to <tt>cache_key</tt>
|
76
|
+
# Fails otherwise.
|
77
|
+
#
|
78
|
+
# <tt>cache_key</tt> returns a (self-expiring) unique key for the object,
|
79
|
+
# and is part of the (self-expiring) cache_key, which is used by the
|
80
|
+
# adapter. It is not required unless caching is enabled.
|
81
|
+
def test_cache_key
|
82
|
+
assert_respond_to resource, :cache_key
|
83
|
+
actual_arity = resource.method(:cache_key).arity
|
84
|
+
assert_includes [-1, 0], actual_arity, "expected #{actual_arity.inspect} to be 0 or -1"
|
85
|
+
end
|
84
86
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
87
|
+
# Passes if the object responds to <tt>updated_at</tt> and if it takes no
|
88
|
+
# arguments.
|
89
|
+
# Fails otherwise.
|
90
|
+
#
|
91
|
+
# <tt>updated_at</tt> returns a Time object or iso8601 string and
|
92
|
+
# is part of the (self-expiring) cache_key, which is used by the adapter.
|
93
|
+
# It is not required unless caching is enabled.
|
94
|
+
def test_updated_at
|
95
|
+
assert_respond_to resource, :updated_at
|
96
|
+
actual_arity = resource.method(:updated_at).arity
|
97
|
+
assert_equal 0, actual_arity
|
98
|
+
end
|
97
99
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
100
|
+
# Passes if the object responds to <tt>id</tt> and if it takes no
|
101
|
+
# arguments.
|
102
|
+
# Fails otherwise.
|
103
|
+
#
|
104
|
+
# <tt>id</tt> returns a unique identifier for the object.
|
105
|
+
# It is not required unless caching is enabled.
|
106
|
+
def test_id
|
107
|
+
assert_respond_to resource, :id
|
108
|
+
assert_equal 0, resource.method(:id).arity
|
109
|
+
end
|
108
110
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
111
|
+
# Passes if the object's class responds to <tt>model_name</tt> and if it
|
112
|
+
# is in an instance of +ActiveModel::Name+.
|
113
|
+
# Fails otherwise.
|
114
|
+
#
|
115
|
+
# <tt>model_name</tt> returns an ActiveModel::Name instance.
|
116
|
+
# It is used by the serializer to identify the object's type.
|
117
|
+
# It is not required unless caching is enabled.
|
118
|
+
def test_model_name
|
119
|
+
resource_class = resource.class
|
120
|
+
assert_respond_to resource_class, :model_name
|
121
|
+
assert_instance_of resource_class.model_name, ActiveModel::Name
|
122
|
+
end
|
121
123
|
|
122
|
-
|
123
|
-
|
124
|
-
|
124
|
+
def test_active_model_errors
|
125
|
+
assert_respond_to resource, :errors
|
126
|
+
end
|
125
127
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
128
|
+
def test_active_model_errors_human_attribute_name
|
129
|
+
assert_respond_to resource.class, :human_attribute_name
|
130
|
+
assert_equal(-2, resource.class.method(:human_attribute_name).arity)
|
131
|
+
end
|
130
132
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
133
|
+
def test_active_model_errors_lookup_ancestors
|
134
|
+
assert_respond_to resource.class, :lookup_ancestors
|
135
|
+
assert_equal 0, resource.class.method(:lookup_ancestors).arity
|
136
|
+
end
|
135
137
|
|
136
|
-
|
138
|
+
private
|
137
139
|
|
138
|
-
|
139
|
-
|
140
|
-
|
140
|
+
def resource
|
141
|
+
@resource or fail "'@resource' must be set as the linted object"
|
142
|
+
end
|
141
143
|
|
142
|
-
|
143
|
-
|
144
|
+
def assert_instance_of(result, name)
|
145
|
+
assert result.instance_of?(name), "#{result} should be an instance of #{name}"
|
146
|
+
end
|
147
|
+
end
|
144
148
|
end
|
145
149
|
end
|
146
150
|
end
|
@@ -75,10 +75,10 @@ module ActiveModel
|
|
75
75
|
|
76
76
|
if block
|
77
77
|
block_value = instance_exec(serializer, &block)
|
78
|
-
if block_value
|
79
|
-
serializer.read_attribute_for_serialization(name)
|
80
|
-
else
|
78
|
+
if block_value != :nil
|
81
79
|
block_value
|
80
|
+
elsif @_include_data
|
81
|
+
serializer.read_attribute_for_serialization(name)
|
82
82
|
end
|
83
83
|
else
|
84
84
|
serializer.read_attribute_for_serialization(name)
|
@@ -1,9 +1,9 @@
|
|
1
1
|
require 'thread_safe'
|
2
|
+
require 'jsonapi/include_directive'
|
2
3
|
require 'active_model/serializer/collection_serializer'
|
3
4
|
require 'active_model/serializer/array_serializer'
|
4
5
|
require 'active_model/serializer/error_serializer'
|
5
6
|
require 'active_model/serializer/errors_serializer'
|
6
|
-
require 'active_model/serializer/include_tree'
|
7
7
|
require 'active_model/serializer/associations'
|
8
8
|
require 'active_model/serializer/attributes'
|
9
9
|
require 'active_model/serializer/caching'
|
@@ -98,6 +98,22 @@ module ActiveModel
|
|
98
98
|
end
|
99
99
|
end
|
100
100
|
|
101
|
+
# @api private
|
102
|
+
def self.include_directive_from_options(options)
|
103
|
+
if options[:include_directive]
|
104
|
+
options[:include_directive]
|
105
|
+
elsif options[:include]
|
106
|
+
JSONAPI::IncludeDirective.new(options[:include], allow_wildcard: true)
|
107
|
+
else
|
108
|
+
ActiveModelSerializers.default_include_directive
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# @api private
|
113
|
+
def self.serialization_adapter_instance
|
114
|
+
@serialization_adapter_instance ||= ActiveModelSerializers::Adapter::Attributes
|
115
|
+
end
|
116
|
+
|
101
117
|
attr_accessor :object, :root, :scope
|
102
118
|
|
103
119
|
# `scope_name` is set as :current_user by default in the controller.
|
@@ -109,10 +125,9 @@ module ActiveModel
|
|
109
125
|
self.root = instance_options[:root]
|
110
126
|
self.scope = instance_options[:scope]
|
111
127
|
|
112
|
-
scope_name = instance_options[:scope_name]
|
113
|
-
|
114
|
-
|
115
|
-
end
|
128
|
+
return if !(scope_name = instance_options[:scope_name]) || respond_to?(scope_name)
|
129
|
+
|
130
|
+
define_singleton_method scope_name, -> { scope }
|
116
131
|
end
|
117
132
|
|
118
133
|
def success?
|
@@ -123,9 +138,7 @@ module ActiveModel
|
|
123
138
|
# associations, similar to how ActiveModel::Serializers::JSON is used
|
124
139
|
# in ActiveRecord::Base.
|
125
140
|
#
|
126
|
-
# TODO:
|
127
|
-
# +serializable_hash_for_single_resource(options)+
|
128
|
-
# and include <tt>ActiveModel::Serializers::JSON</tt>.
|
141
|
+
# TODO: Include <tt>ActiveModel::Serializers::JSON</tt>.
|
129
142
|
# So that the below is true:
|
130
143
|
# @param options [nil, Hash] The same valid options passed to `serializable_hash`
|
131
144
|
# (:only, :except, :methods, and :include).
|
@@ -149,11 +162,13 @@ module ActiveModel
|
|
149
162
|
# serializer.as_json(include: :posts)
|
150
163
|
# # Second level and higher order associations work as well:
|
151
164
|
# serializer.as_json(include: { posts: { include: { comments: { only: :body } }, only: :title } })
|
152
|
-
def serializable_hash(
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
165
|
+
def serializable_hash(adapter_options = nil, options = {}, adapter_instance = self.class.serialization_adapter_instance)
|
166
|
+
adapter_options ||= {}
|
167
|
+
options[:include_directive] ||= ActiveModel::Serializer.include_directive_from_options(adapter_options)
|
168
|
+
cached_attributes = adapter_options[:cached_attributes] ||= {}
|
169
|
+
resource = fetch_attributes(options[:fields], cached_attributes, adapter_instance)
|
170
|
+
relationships = resource_relationships(adapter_options, options, adapter_instance)
|
171
|
+
resource.merge(relationships)
|
157
172
|
end
|
158
173
|
alias to_hash serializable_hash
|
159
174
|
alias to_h serializable_hash
|
@@ -178,13 +193,40 @@ module ActiveModel
|
|
178
193
|
def read_attribute_for_serialization(attr)
|
179
194
|
if respond_to?(attr)
|
180
195
|
send(attr)
|
181
|
-
elsif self.class._fragmented
|
182
|
-
self.class._fragmented.read_attribute_for_serialization(attr)
|
183
196
|
else
|
184
197
|
object.read_attribute_for_serialization(attr)
|
185
198
|
end
|
186
199
|
end
|
187
200
|
|
201
|
+
# @api private
|
202
|
+
def resource_relationships(adapter_options, options, adapter_instance)
|
203
|
+
relationships = {}
|
204
|
+
include_directive = options.fetch(:include_directive)
|
205
|
+
associations(include_directive).each do |association|
|
206
|
+
adapter_opts = adapter_options.merge(include_directive: include_directive[association.key])
|
207
|
+
relationships[association.key] ||= relationship_value_for(association, adapter_opts, adapter_instance)
|
208
|
+
end
|
209
|
+
|
210
|
+
relationships
|
211
|
+
end
|
212
|
+
|
213
|
+
# @api private
|
214
|
+
def relationship_value_for(association, adapter_options, adapter_instance)
|
215
|
+
return association.options[:virtual_value] if association.options[:virtual_value]
|
216
|
+
association_serializer = association.serializer
|
217
|
+
association_object = association_serializer && association_serializer.object
|
218
|
+
return unless association_object
|
219
|
+
|
220
|
+
relationship_value = association_serializer.serializable_hash(adapter_options, {}, adapter_instance)
|
221
|
+
|
222
|
+
if association.options[:polymorphic] && relationship_value
|
223
|
+
polymorphic_type = association_object.class.name.underscore
|
224
|
+
relationship_value = { type: polymorphic_type, polymorphic_type.to_sym => relationship_value }
|
225
|
+
end
|
226
|
+
|
227
|
+
relationship_value
|
228
|
+
end
|
229
|
+
|
188
230
|
protected
|
189
231
|
|
190
232
|
attr_accessor :instance_options
|
@@ -1,75 +1,10 @@
|
|
1
1
|
module ActiveModelSerializers
|
2
2
|
module Adapter
|
3
3
|
class Attributes < Base
|
4
|
-
def initialize(serializer, options = {})
|
5
|
-
super
|
6
|
-
@include_tree = ActiveModel::Serializer::IncludeTree.from_include_args(options[:include] || '*')
|
7
|
-
@cached_attributes = options[:cache_attributes] || {}
|
8
|
-
end
|
9
|
-
|
10
4
|
def serializable_hash(options = nil)
|
11
5
|
options = serialization_options(options)
|
12
|
-
|
13
|
-
|
14
|
-
serializable_hash_for_collection(options)
|
15
|
-
else
|
16
|
-
serializable_hash_for_single_resource(options)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
private
|
21
|
-
|
22
|
-
def serializable_hash_for_collection(options)
|
23
|
-
cache_attributes
|
24
|
-
|
25
|
-
serializer.map { |s| Attributes.new(s, instance_options).serializable_hash(options) }
|
26
|
-
end
|
27
|
-
|
28
|
-
def serializable_hash_for_single_resource(options)
|
29
|
-
resource = resource_object_for(options)
|
30
|
-
relationships = resource_relationships(options)
|
31
|
-
resource.merge(relationships)
|
32
|
-
end
|
33
|
-
|
34
|
-
def resource_relationships(options)
|
35
|
-
relationships = {}
|
36
|
-
serializer.associations(@include_tree).each do |association|
|
37
|
-
relationships[association.key] ||= relationship_value_for(association, options)
|
38
|
-
end
|
39
|
-
|
40
|
-
relationships
|
41
|
-
end
|
42
|
-
|
43
|
-
def relationship_value_for(association, options)
|
44
|
-
return association.options[:virtual_value] if association.options[:virtual_value]
|
45
|
-
return unless association.serializer && association.serializer.object
|
46
|
-
|
47
|
-
opts = instance_options.merge(include: @include_tree[association.key])
|
48
|
-
relationship_value = Attributes.new(association.serializer, opts).serializable_hash(options)
|
49
|
-
|
50
|
-
if association.options[:polymorphic] && relationship_value
|
51
|
-
polymorphic_type = association.serializer.object.class.name.underscore
|
52
|
-
relationship_value = { type: polymorphic_type, polymorphic_type.to_sym => relationship_value }
|
53
|
-
end
|
54
|
-
|
55
|
-
relationship_value
|
56
|
-
end
|
57
|
-
|
58
|
-
# Set @cached_attributes
|
59
|
-
def cache_attributes
|
60
|
-
return if @cached_attributes.present?
|
61
|
-
|
62
|
-
@cached_attributes = ActiveModel::Serializer.cache_read_multi(serializer, self, @include_tree)
|
63
|
-
end
|
64
|
-
|
65
|
-
def resource_object_for(options)
|
66
|
-
if serializer.class.cache_enabled?
|
67
|
-
@cached_attributes.fetch(serializer.cache_key(self)) do
|
68
|
-
serializer.cached_fields(options[:fields], self)
|
69
|
-
end
|
70
|
-
else
|
71
|
-
serializer.cached_fields(options[:fields], self)
|
72
|
-
end
|
6
|
+
options[:fields] ||= instance_options[:fields]
|
7
|
+
serializer.serializable_hash(instance_options, options, self)
|
73
8
|
end
|
74
9
|
end
|
75
10
|
end
|
@@ -8,6 +8,40 @@ module ActiveModelSerializers
|
|
8
8
|
ActiveModelSerializers::Adapter.register(subclass)
|
9
9
|
end
|
10
10
|
|
11
|
+
# Sets the default transform for the adapter.
|
12
|
+
#
|
13
|
+
# @return [Symbol] the default transform for the adapter
|
14
|
+
def self.default_key_transform
|
15
|
+
:unaltered
|
16
|
+
end
|
17
|
+
|
18
|
+
# Determines the transform to use in order of precedence:
|
19
|
+
# adapter option, global config, adapter default.
|
20
|
+
#
|
21
|
+
# @param options [Object]
|
22
|
+
# @return [Symbol] the transform to use
|
23
|
+
def self.transform(options)
|
24
|
+
return options[:key_transform] if options && options[:key_transform]
|
25
|
+
ActiveModelSerializers.config.key_transform || default_key_transform
|
26
|
+
end
|
27
|
+
|
28
|
+
# Transforms the casing of the supplied value.
|
29
|
+
#
|
30
|
+
# @param value [Object] the value to be transformed
|
31
|
+
# @param options [Object] serializable resource options
|
32
|
+
# @return [Symbol] the default transform for the adapter
|
33
|
+
def self.transform_key_casing!(value, options)
|
34
|
+
KeyTransform.send(transform(options), value)
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.cache_key
|
38
|
+
@cache_key ||= ActiveModelSerializers::Adapter.registered_name(self)
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.fragment_cache(cached_hash, non_cached_hash)
|
42
|
+
non_cached_hash.merge cached_hash
|
43
|
+
end
|
44
|
+
|
11
45
|
attr_reader :serializer, :instance_options
|
12
46
|
|
13
47
|
def initialize(serializer, options = {})
|
@@ -15,10 +49,6 @@ module ActiveModelSerializers
|
|
15
49
|
@instance_options = options
|
16
50
|
end
|
17
51
|
|
18
|
-
def cached_name
|
19
|
-
@cached_name ||= self.class.name.demodulize.underscore
|
20
|
-
end
|
21
|
-
|
22
52
|
# Subclasses that implement this method must first call
|
23
53
|
# options = serialization_options(options)
|
24
54
|
def serializable_hash(_options = nil)
|
@@ -29,14 +59,12 @@ module ActiveModelSerializers
|
|
29
59
|
serializable_hash(options)
|
30
60
|
end
|
31
61
|
|
32
|
-
def
|
33
|
-
|
62
|
+
def cache_key
|
63
|
+
self.class.cache_key
|
34
64
|
end
|
35
65
|
|
36
|
-
def
|
37
|
-
|
38
|
-
yield
|
39
|
-
end
|
66
|
+
def fragment_cache(cached_hash, non_cached_hash)
|
67
|
+
self.class.fragment_cache(cached_hash, non_cached_hash)
|
40
68
|
end
|
41
69
|
|
42
70
|
private
|
@@ -50,34 +78,6 @@ module ActiveModelSerializers
|
|
50
78
|
def root
|
51
79
|
serializer.json_key.to_sym if serializer.json_key
|
52
80
|
end
|
53
|
-
|
54
|
-
class << self
|
55
|
-
# Sets the default transform for the adapter.
|
56
|
-
#
|
57
|
-
# @return [Symbol] the default transform for the adapter
|
58
|
-
def default_key_transform
|
59
|
-
:unaltered
|
60
|
-
end
|
61
|
-
|
62
|
-
# Determines the transform to use in order of precedence:
|
63
|
-
# adapter option, global config, adapter default.
|
64
|
-
#
|
65
|
-
# @param options [Object]
|
66
|
-
# @return [Symbol] the transform to use
|
67
|
-
def transform(options)
|
68
|
-
return options[:key_transform] if options && options[:key_transform]
|
69
|
-
ActiveModelSerializers.config.key_transform || default_key_transform
|
70
|
-
end
|
71
|
-
|
72
|
-
# Transforms the casing of the supplied value.
|
73
|
-
#
|
74
|
-
# @param value [Object] the value to be transformed
|
75
|
-
# @param options [Object] serializable resource options
|
76
|
-
# @return [Symbol] the default transform for the adapter
|
77
|
-
def transform_key_casing!(value, options)
|
78
|
-
KeyTransform.send(transform(options), value)
|
79
|
-
end
|
80
|
-
end
|
81
81
|
end
|
82
82
|
end
|
83
83
|
end
|
@@ -2,6 +2,7 @@ module ActiveModelSerializers
|
|
2
2
|
module Adapter
|
3
3
|
class JsonApi < Base
|
4
4
|
class PaginationLinks
|
5
|
+
MissingSerializationContextError = Class.new(KeyError)
|
5
6
|
FIRST_PAGE = 1
|
6
7
|
|
7
8
|
attr_reader :collection, :context
|
@@ -9,7 +10,13 @@ module ActiveModelSerializers
|
|
9
10
|
def initialize(collection, adapter_options)
|
10
11
|
@collection = collection
|
11
12
|
@adapter_options = adapter_options
|
12
|
-
@context = adapter_options.fetch(:serialization_context)
|
13
|
+
@context = adapter_options.fetch(:serialization_context) do
|
14
|
+
fail MissingSerializationContextError, <<-EOF.freeze
|
15
|
+
JsonApi::PaginationLinks requires a ActiveModelSerializers::SerializationContext.
|
16
|
+
Please pass a ':serialization_context' option or
|
17
|
+
override CollectionSerializer#paginated? to return 'false'.
|
18
|
+
EOF
|
19
|
+
end
|
13
20
|
end
|
14
21
|
|
15
22
|
def as_json
|