active_model_serializers 0.10.0 → 0.10.7
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 +5 -5
- data/.rubocop.yml +6 -5
- data/.travis.yml +30 -21
- data/CHANGELOG.md +172 -2
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +23 -4
- data/README.md +166 -28
- data/Rakefile +3 -32
- data/active_model_serializers.gemspec +22 -25
- data/appveyor.yml +10 -6
- data/bin/rubocop +38 -0
- data/docs/README.md +2 -1
- data/docs/general/adapters.md +35 -11
- data/docs/general/caching.md +7 -1
- data/docs/general/configuration_options.md +86 -1
- data/docs/general/deserialization.md +1 -1
- data/docs/general/fields.md +31 -0
- data/docs/general/getting_started.md +1 -1
- data/docs/general/logging.md +7 -0
- data/docs/general/rendering.md +63 -25
- data/docs/general/serializers.md +125 -14
- data/docs/howto/add_pagination_links.md +16 -17
- data/docs/howto/add_relationship_links.md +140 -0
- data/docs/howto/add_root_key.md +11 -0
- data/docs/howto/grape_integration.md +42 -0
- data/docs/howto/outside_controller_use.md +12 -4
- data/docs/howto/passing_arbitrary_options.md +2 -2
- data/docs/howto/serialize_poro.md +46 -5
- data/docs/howto/test.md +2 -0
- data/docs/howto/upgrade_from_0_8_to_0_10.md +265 -0
- data/docs/integrations/ember-and-json-api.md +67 -32
- data/docs/jsonapi/schema.md +1 -1
- data/lib/action_controller/serialization.rb +13 -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/association.rb +62 -10
- data/lib/active_model/serializer/belongs_to_reflection.rb +4 -3
- data/lib/active_model/serializer/collection_serializer.rb +39 -13
- data/lib/active_model/serializer/{caching.rb → concerns/caching.rb} +82 -115
- 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 +3 -3
- data/lib/active_model/serializer/has_one_reflection.rb +1 -4
- data/lib/active_model/serializer/lazy_association.rb +95 -0
- data/lib/active_model/serializer/lint.rb +134 -130
- data/lib/active_model/serializer/reflection.rb +127 -67
- data/lib/active_model/serializer/version.rb +1 -1
- data/lib/active_model/serializer.rb +297 -79
- data/lib/active_model_serializers/adapter/attributes.rb +3 -66
- data/lib/active_model_serializers/adapter/base.rb +39 -39
- data/lib/active_model_serializers/adapter/json_api/deserialization.rb +2 -2
- data/lib/active_model_serializers/adapter/json_api/link.rb +1 -1
- data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +47 -21
- data/lib/active_model_serializers/adapter/json_api/relationship.rb +75 -23
- data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +39 -10
- data/lib/active_model_serializers/adapter/json_api.rb +71 -57
- 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/lookup_chain.rb +80 -0
- data/lib/active_model_serializers/model.rb +109 -28
- 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/serializable_resource.rb +6 -5
- data/lib/active_model_serializers/serialization_context.rb +10 -3
- data/lib/active_model_serializers/test/schema.rb +2 -2
- data/lib/active_model_serializers.rb +16 -1
- data/lib/generators/rails/resource_override.rb +1 -1
- data/lib/generators/rails/serializer_generator.rb +4 -4
- 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/lib/tasks/rubocop.rake +53 -0
- data/test/action_controller/adapter_selector_test.rb +14 -5
- 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/deserialization_test.rb +1 -1
- data/test/action_controller/json_api/errors_test.rb +8 -9
- data/test/action_controller/json_api/fields_test.rb +66 -0
- data/test/action_controller/json_api/linked_test.rb +29 -24
- data/test/action_controller/json_api/pagination_test.rb +31 -23
- data/test/action_controller/json_api/transform_test.rb +11 -3
- data/test/action_controller/lookup_proc_test.rb +49 -0
- data/test/action_controller/namespace_lookup_test.rb +232 -0
- data/test/action_controller/serialization_scope_name_test.rb +12 -6
- data/test/action_controller/serialization_test.rb +12 -9
- data/test/active_model_serializers/json_pointer_test.rb +15 -13
- data/test/active_model_serializers/model_test.rb +137 -4
- data/test/active_model_serializers/railtie_test_isolated.rb +12 -7
- data/test/active_model_serializers/register_jsonapi_renderer_test_isolated.rb +161 -0
- data/test/active_model_serializers/serialization_context_test_isolated.rb +23 -10
- data/test/active_model_serializers/test/schema_test.rb +3 -2
- data/test/adapter/attributes_test.rb +40 -0
- data/test/adapter/json/collection_test.rb +14 -0
- data/test/adapter/json/has_many_test.rb +10 -2
- data/test/adapter/json/transform_test.rb +15 -15
- 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/fields_test.rb +12 -3
- data/test/adapter/json_api/has_many_test.rb +49 -20
- data/test/adapter/json_api/include_data_if_sideloaded_test.rb +213 -0
- data/test/adapter/json_api/json_api_test.rb +5 -7
- data/test/adapter/json_api/linked_test.rb +33 -12
- data/test/adapter/json_api/links_test.rb +4 -2
- data/test/adapter/json_api/pagination_links_test.rb +53 -13
- data/test/adapter/json_api/parse_test.rb +1 -1
- data/test/adapter/json_api/relationship_test.rb +309 -73
- data/test/adapter/json_api/resource_meta_test.rb +3 -3
- data/test/adapter/json_api/transform_test.rb +263 -253
- data/test/adapter/json_api/type_test.rb +168 -36
- data/test/adapter/json_test.rb +8 -7
- data/test/adapter/null_test.rb +1 -2
- data/test/adapter/polymorphic_test.rb +52 -5
- data/test/adapter_test.rb +1 -1
- data/test/benchmark/app.rb +1 -1
- data/test/benchmark/benchmarking_support.rb +1 -1
- data/test/benchmark/bm_active_record.rb +81 -0
- data/test/benchmark/bm_adapter.rb +38 -0
- data/test/benchmark/bm_caching.rb +16 -16
- data/test/benchmark/bm_lookup_chain.rb +83 -0
- data/test/benchmark/bm_transform.rb +21 -10
- data/test/benchmark/controllers.rb +16 -17
- data/test/benchmark/fixtures.rb +72 -72
- data/test/cache_test.rb +235 -69
- data/test/collection_serializer_test.rb +31 -14
- data/test/fixtures/active_record.rb +45 -10
- data/test/fixtures/poro.rb +124 -181
- data/test/generators/serializer_generator_test.rb +23 -5
- data/test/grape_test.rb +170 -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/association_macros_test.rb +3 -2
- data/test/serializers/associations_test.rb +222 -49
- data/test/serializers/attribute_test.rb +5 -3
- data/test/serializers/attributes_test.rb +1 -1
- data/test/serializers/caching_configuration_test_isolated.rb +6 -6
- data/test/serializers/fieldset_test.rb +1 -1
- data/test/serializers/meta_test.rb +12 -6
- data/test/serializers/options_test.rb +17 -6
- data/test/serializers/read_attribute_for_serialization_test.rb +3 -3
- data/test/serializers/reflection_test.rb +427 -0
- data/test/serializers/root_test.rb +1 -1
- data/test/serializers/serialization_test.rb +2 -2
- data/test/serializers/serializer_for_test.rb +12 -10
- data/test/serializers/serializer_for_with_namespace_test.rb +88 -0
- data/test/support/isolated_unit.rb +9 -4
- data/test/support/rails5_shims.rb +8 -2
- data/test/support/rails_app.rb +2 -9
- data/test/support/serialization_testing.rb +31 -5
- data/test/test_helper.rb +13 -0
- metadata +130 -71
- data/.rubocop_todo.yml +0 -167
- data/docs/ARCHITECTURE.md +0 -126
- data/lib/active_model/serializer/associations.rb +0 -100
- data/lib/active_model/serializer/attributes.rb +0 -82
- data/lib/active_model/serializer/collection_reflection.rb +0 -7
- data/lib/active_model/serializer/configuration.rb +0 -35
- data/lib/active_model/serializer/include_tree.rb +0 -111
- data/lib/active_model/serializer/links.rb +0 -35
- data/lib/active_model/serializer/meta.rb +0 -29
- data/lib/active_model/serializer/singular_reflection.rb +0 -7
- data/lib/active_model/serializer/type.rb +0 -25
- data/lib/active_model_serializers/key_transform.rb +0 -70
- data/test/active_model_serializers/key_transform_test.rb +0 -263
- data/test/adapter/json_api/has_many_embed_ids_test.rb +0 -43
- data/test/adapter/json_api/relationships_test.rb +0 -199
- data/test/adapter/json_api/resource_identifier_test.rb +0 -85
- 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
data/.rubocop_todo.yml
DELETED
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
# This configuration was generated by
|
|
2
|
-
# `rubocop --auto-gen-config`
|
|
3
|
-
# on 2016-03-08 22:29:52 +0100 using RuboCop version 0.37.2.
|
|
4
|
-
# The point is for the user to remove these configuration records
|
|
5
|
-
# one by one as the offenses are removed from the code base.
|
|
6
|
-
# Note that changes in the inspected code, or installation of new
|
|
7
|
-
# versions of RuboCop, may require this file to be generated again.
|
|
8
|
-
|
|
9
|
-
# Offense count: 2
|
|
10
|
-
Lint/HandleExceptions:
|
|
11
|
-
Exclude:
|
|
12
|
-
- 'Rakefile'
|
|
13
|
-
|
|
14
|
-
# Offense count: 2
|
|
15
|
-
# Cop supports --auto-correct.
|
|
16
|
-
# Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods.
|
|
17
|
-
Lint/UnusedMethodArgument:
|
|
18
|
-
Exclude:
|
|
19
|
-
- 'test/lint_test.rb'
|
|
20
|
-
|
|
21
|
-
# Offense count: 4
|
|
22
|
-
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
|
23
|
-
# SupportedStyles: strict, flexible
|
|
24
|
-
Rails/TimeZone:
|
|
25
|
-
Exclude:
|
|
26
|
-
- 'test/action_controller/serialization_test.rb'
|
|
27
|
-
- 'test/serializers/cache_test.rb'
|
|
28
|
-
|
|
29
|
-
# Offense count: 16
|
|
30
|
-
# Cop supports --auto-correct.
|
|
31
|
-
# Configuration parameters: EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle, SupportedLastArgumentHashStyles.
|
|
32
|
-
# SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit
|
|
33
|
-
Style/AlignHash:
|
|
34
|
-
Exclude:
|
|
35
|
-
- 'test/action_controller/json_api/pagination_test.rb'
|
|
36
|
-
|
|
37
|
-
# Offense count: 27
|
|
38
|
-
# Cop supports --auto-correct.
|
|
39
|
-
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
|
40
|
-
# SupportedStyles: braces, no_braces, context_dependent
|
|
41
|
-
Style/BracesAroundHashParameters:
|
|
42
|
-
Exclude:
|
|
43
|
-
- 'test/action_controller/adapter_selector_test.rb'
|
|
44
|
-
- 'test/action_controller/json_api/pagination_test.rb'
|
|
45
|
-
- 'test/adapter/json_api/linked_test.rb'
|
|
46
|
-
- 'test/adapter/json_api/pagination_links_test.rb'
|
|
47
|
-
- 'test/adapter/null_test.rb'
|
|
48
|
-
- 'test/adapter_test.rb'
|
|
49
|
-
- 'test/collection_serializer_test.rb'
|
|
50
|
-
- 'test/serializable_resource_test.rb'
|
|
51
|
-
- 'test/serializers/associations_test.rb'
|
|
52
|
-
- 'test/serializers/attributes_test.rb'
|
|
53
|
-
- 'test/serializers/root_test.rb'
|
|
54
|
-
|
|
55
|
-
# Offense count: 271
|
|
56
|
-
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
|
57
|
-
# SupportedStyles: nested, compact
|
|
58
|
-
Style/ClassAndModuleChildren:
|
|
59
|
-
Enabled: false
|
|
60
|
-
|
|
61
|
-
# Offense count: 6
|
|
62
|
-
# Cop supports --auto-correct.
|
|
63
|
-
Style/CommentIndentation:
|
|
64
|
-
Exclude:
|
|
65
|
-
- 'active_model_serializers.gemspec'
|
|
66
|
-
|
|
67
|
-
# Offense count: 1
|
|
68
|
-
Style/DoubleNegation:
|
|
69
|
-
Exclude:
|
|
70
|
-
- 'lib/active_model/serializable_resource.rb'
|
|
71
|
-
|
|
72
|
-
# Offense count: 1
|
|
73
|
-
# Configuration parameters: MinBodyLength.
|
|
74
|
-
Style/GuardClause:
|
|
75
|
-
Exclude:
|
|
76
|
-
- 'lib/active_model/serializer.rb'
|
|
77
|
-
|
|
78
|
-
# Offense count: 58
|
|
79
|
-
# Cop supports --auto-correct.
|
|
80
|
-
# Configuration parameters: EnforcedStyle, SupportedStyles, UseHashRocketsWithSymbolValues.
|
|
81
|
-
# SupportedStyles: ruby19, ruby19_no_mixed_keys, hash_rockets
|
|
82
|
-
Style/HashSyntax:
|
|
83
|
-
Enabled: false
|
|
84
|
-
|
|
85
|
-
# Offense count: 4
|
|
86
|
-
# Cop supports --auto-correct.
|
|
87
|
-
# Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth.
|
|
88
|
-
# SupportedStyles: special_inside_parentheses, consistent, align_brackets
|
|
89
|
-
Style/IndentArray:
|
|
90
|
-
Enabled: false
|
|
91
|
-
|
|
92
|
-
# Offense count: 10
|
|
93
|
-
# Cop supports --auto-correct.
|
|
94
|
-
# Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth.
|
|
95
|
-
# SupportedStyles: special_inside_parentheses, consistent, align_braces
|
|
96
|
-
Style/IndentHash:
|
|
97
|
-
Enabled: false
|
|
98
|
-
|
|
99
|
-
# Offense count: 1
|
|
100
|
-
# Cop supports --auto-correct.
|
|
101
|
-
Style/Lambda:
|
|
102
|
-
Exclude:
|
|
103
|
-
- 'lib/active_model/serializer.rb'
|
|
104
|
-
|
|
105
|
-
# Offense count: 1
|
|
106
|
-
# Cop supports --auto-correct.
|
|
107
|
-
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
|
108
|
-
# SupportedStyles: require_parentheses, require_no_parentheses, require_no_parentheses_except_multiline
|
|
109
|
-
Style/MethodDefParentheses:
|
|
110
|
-
Enabled: false
|
|
111
|
-
|
|
112
|
-
# Offense count: 1
|
|
113
|
-
# Cop supports --auto-correct.
|
|
114
|
-
# Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth.
|
|
115
|
-
# SupportedStyles: aligned, indented
|
|
116
|
-
Style/MultilineOperationIndentation:
|
|
117
|
-
Enabled: false
|
|
118
|
-
|
|
119
|
-
# Offense count: 1
|
|
120
|
-
# Cop supports --auto-correct.
|
|
121
|
-
Style/NegatedIf:
|
|
122
|
-
Exclude:
|
|
123
|
-
- 'lib/action_controller/serialization.rb'
|
|
124
|
-
|
|
125
|
-
# Offense count: 1
|
|
126
|
-
# Cop supports --auto-correct.
|
|
127
|
-
Style/PerlBackrefs:
|
|
128
|
-
Exclude:
|
|
129
|
-
- 'test/fixtures/poro.rb'
|
|
130
|
-
|
|
131
|
-
# Offense count: 3
|
|
132
|
-
# Configuration parameters: NamePrefix, NamePrefixBlacklist, NameWhitelist.
|
|
133
|
-
# NamePrefix: is_, has_, have_
|
|
134
|
-
# NamePrefixBlacklist: is_, has_, have_
|
|
135
|
-
# NameWhitelist: is_a?
|
|
136
|
-
Style/PredicateName:
|
|
137
|
-
Exclude:
|
|
138
|
-
- 'lib/active_model/serializer/associations.rb'
|
|
139
|
-
- 'test/action_controller/json_api/linked_test.rb'
|
|
140
|
-
|
|
141
|
-
# Offense count: 1
|
|
142
|
-
# Cop supports --auto-correct.
|
|
143
|
-
Style/RedundantSelf:
|
|
144
|
-
Exclude:
|
|
145
|
-
- 'test/fixtures/poro.rb'
|
|
146
|
-
|
|
147
|
-
# Offense count: 1
|
|
148
|
-
# Cop supports --auto-correct.
|
|
149
|
-
# Configuration parameters: AllowIfMethodIsEmpty.
|
|
150
|
-
Style/SingleLineMethods:
|
|
151
|
-
Exclude:
|
|
152
|
-
- 'test/serializers/serializer_for_test.rb'
|
|
153
|
-
|
|
154
|
-
# Offense count: 4
|
|
155
|
-
# Cop supports --auto-correct.
|
|
156
|
-
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
|
157
|
-
# SupportedStyles: single_quotes, double_quotes
|
|
158
|
-
Style/StringLiteralsInInterpolation:
|
|
159
|
-
Enabled: false
|
|
160
|
-
|
|
161
|
-
# Offense count: 1
|
|
162
|
-
# Cop supports --auto-correct.
|
|
163
|
-
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
|
164
|
-
# SupportedStyles: final_newline, final_blank_line
|
|
165
|
-
Style/TrailingBlankLines:
|
|
166
|
-
Exclude:
|
|
167
|
-
- 'test/adapter/null_test.rb'
|
data/docs/ARCHITECTURE.md
DELETED
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
[Back to Guides](README.md)
|
|
2
|
-
|
|
3
|
-
This document focuses on architecture the 0.10.x version of ActiveModelSerializers. If you are interested in the architecture of the 0.8 or 0.9 versions,
|
|
4
|
-
please refer to the [0.8 README](https://github.com/rails-api/active_model_serializers/blob/0-8-stable/README.md) or
|
|
5
|
-
[0.9 README](https://github.com/rails-api/active_model_serializers/blob/0-9-stable/README.md).
|
|
6
|
-
|
|
7
|
-
The original design is also available [here](https://github.com/rails-api/active_model_serializers/blob/d72b66d4c5355b0ff0a75a04895fcc4ea5b0c65e/README.textile).
|
|
8
|
-
|
|
9
|
-
# ARCHITECTURE
|
|
10
|
-
|
|
11
|
-
An **`ActiveModel::Serializer`** wraps a [serializable resource](https://github.com/rails/rails/blob/4-2-stable/activemodel/lib/active_model/serialization.rb)
|
|
12
|
-
and exposes an `attributes` method, among a few others.
|
|
13
|
-
It allows you to specify which attributes and associations should be represented in the serializatation of the resource.
|
|
14
|
-
It requires an adapter to transform its attributes into a JSON document; it cannot be serialized itself.
|
|
15
|
-
It may be useful to think of it as a
|
|
16
|
-
[presenter](http://blog.steveklabnik.com/posts/2011-09-09-better-ruby-presenters).
|
|
17
|
-
|
|
18
|
-
The **`ActiveModel::ArraySerializer`** represent a collection of resources as serializers
|
|
19
|
-
and, if there is no serializer, primitives.
|
|
20
|
-
|
|
21
|
-
The **`ActiveModel::Adapter`** describes the structure of the JSON document generated from a
|
|
22
|
-
serializer. For example, the `Attributes` example represents each serializer as its
|
|
23
|
-
unmodified attributes. The `JsonApi` adapter represents the serializer as a [JSON
|
|
24
|
-
API](http://jsonapi.org/) document.
|
|
25
|
-
|
|
26
|
-
The **`ActiveModelSerializers::SerializableResource`** acts to coordinate the serializer(s) and adapter
|
|
27
|
-
to an object that responds to `to_json`, and `as_json`. It is used in the controller to
|
|
28
|
-
encapsulate the serialization resource when rendered. However, it can also be used on its own
|
|
29
|
-
to serialize a resource outside of a controller, as well.
|
|
30
|
-
|
|
31
|
-
## Primitive handling
|
|
32
|
-
|
|
33
|
-
Definitions: A primitive is usually a String or Array. There is no serializer
|
|
34
|
-
defined for them; they will be serialized when the resource is converted to JSON (`as_json` or
|
|
35
|
-
`to_json`). (The below also applies for any object with no serializer.)
|
|
36
|
-
|
|
37
|
-
ActiveModelSerializers doesn't handle primitives passed to `render json:` at all.
|
|
38
|
-
|
|
39
|
-
However, when a primitive value is an attribute or in a collection,
|
|
40
|
-
it is not modified.
|
|
41
|
-
|
|
42
|
-
Internally, if no serializer can be found in the controller, the resource is not decorated by
|
|
43
|
-
ActiveModelSerializers.
|
|
44
|
-
|
|
45
|
-
If the collection serializer (ArraySerializer) cannot
|
|
46
|
-
identify a serializer for a resource in its collection, it raises [`NoSerializerError`](https://github.com/rails-api/active_model_serializers/issues/1191#issuecomment-142327128)
|
|
47
|
-
which is rescued in `ActiveModel::Serializer::Reflection#build_association` which sets
|
|
48
|
-
the association value directly:
|
|
49
|
-
|
|
50
|
-
```ruby
|
|
51
|
-
reflection_options[:virtual_value] = association_value.try(:as_json) || association_value
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
(which is called by the adapter as `serializer.associations(*)`.)
|
|
55
|
-
|
|
56
|
-
## How options are parsed
|
|
57
|
-
|
|
58
|
-
High-level overview:
|
|
59
|
-
|
|
60
|
-
- For a collection
|
|
61
|
-
- `:serializer` specifies the collection serializer and
|
|
62
|
-
- `:each_serializer` specifies the serializer for each resource in the collection.
|
|
63
|
-
- For a single resource, the `:serializer` option is the resource serializer.
|
|
64
|
-
- Options are partitioned in serializer options and adapter options. Keys for adapter options are specified by
|
|
65
|
-
[`ADAPTER_OPTION_KEYS`](https://github.com/rails-api/active_model_serializers/blob/master/lib/active_model_serializers/serializable_resource.rb#L5).
|
|
66
|
-
The remaining options are serializer options.
|
|
67
|
-
|
|
68
|
-
Details:
|
|
69
|
-
|
|
70
|
-
1. **ActionController::Serialization**
|
|
71
|
-
1. `serializable_resource = ActiveModelSerializers::SerializableResource.new(resource, options)`
|
|
72
|
-
1. `options` are partitioned into `adapter_opts` and everything else (`serializer_opts`).
|
|
73
|
-
The `adapter_opts` keys are defined in `ActiveModelSerializers::SerializableResource::ADAPTER_OPTION_KEYS`.
|
|
74
|
-
1. **ActiveModelSerializers::SerializableResource**
|
|
75
|
-
1. `if serializable_resource.serializer?` (there is a serializer for the resource, and an adapter is used.)
|
|
76
|
-
- Where `serializer?` is `use_adapter? && !!(serializer)`
|
|
77
|
-
- Where `use_adapter?`: 'True when no explicit adapter given, or explicit value is truthy (non-nil);
|
|
78
|
-
False when explicit adapter is falsy (nil or false)'
|
|
79
|
-
- Where `serializer`:
|
|
80
|
-
1. from explicit `:serializer` option, else
|
|
81
|
-
2. implicitly from resource `ActiveModel::Serializer.serializer_for(resource)`
|
|
82
|
-
1. A side-effect of checking `serializer` is:
|
|
83
|
-
- The `:serializer` option is removed from the serializer_opts hash
|
|
84
|
-
- If the `:each_serializer` option is present, it is removed from the serializer_opts hash and set as the `:serializer` option
|
|
85
|
-
1. The serializer and adapter are created as
|
|
86
|
-
1. `serializer_instance = serializer.new(resource, serializer_opts)`
|
|
87
|
-
2. `adapter_instance = ActiveModel::Serializer::Adapter.create(serializer_instance, adapter_opts)`
|
|
88
|
-
1. **ActiveModel::Serializer::ArraySerializer#new**
|
|
89
|
-
1. If the `serializer_instance` was a `ArraySerializer` and the `:serializer` serializer_opts
|
|
90
|
-
is present, then [that serializer is passed into each resource](https://github.com/rails-api/active_model_serializers/blob/a54d237e2828fe6bab1ea5dfe6360d4ecc8214cd/lib/active_model/serializer/array_serializer.rb#L14-L16).
|
|
91
|
-
1. **ActiveModel::Serializer#attributes** is used by the adapter to get the attributes for
|
|
92
|
-
resource as defined by the serializer.
|
|
93
|
-
|
|
94
|
-
## What does a 'serializable resource' look like?
|
|
95
|
-
|
|
96
|
-
- An `ActiveRecord::Base` object.
|
|
97
|
-
- Any Ruby object that passes the
|
|
98
|
-
[Lint](http://www.rubydoc.info/github/rails-api/active_model_serializers/ActiveModel/Serializer/Lint/Tests)
|
|
99
|
-
[code](https://github.com/rails-api/active_model_serializers/blob/master/lib/active_model/serializer/lint.rb).
|
|
100
|
-
|
|
101
|
-
ActiveModelSerializers provides a
|
|
102
|
-
[`ActiveModelSerializers::Model`](https://github.com/rails-api/active_model_serializers/blob/master/lib/active_model_serializers/model.rb),
|
|
103
|
-
which is a simple serializable PORO (Plain-Old Ruby Object).
|
|
104
|
-
|
|
105
|
-
ActiveModelSerializers::Model may be used either as a template, or in production code.
|
|
106
|
-
|
|
107
|
-
```ruby
|
|
108
|
-
class MyModel < ActiveModelSerializers::Model
|
|
109
|
-
attr_accessor :id, :name, :level
|
|
110
|
-
end
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
The default serializer for `MyModel` would be `MyModelSerializer` whether MyModel is an
|
|
114
|
-
ActiveRecord::Base object or not.
|
|
115
|
-
|
|
116
|
-
Outside of the controller the rules are **exactly** the same as for records. For example:
|
|
117
|
-
|
|
118
|
-
```ruby
|
|
119
|
-
render json: MyModel.new(level: 'awesome'), adapter: :json
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
would be serialized the same as
|
|
123
|
-
|
|
124
|
-
```ruby
|
|
125
|
-
ActiveModelSerializers::SerializableResource.new(MyModel.new(level: 'awesome'), adapter: :json).as_json
|
|
126
|
-
```
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
module ActiveModel
|
|
2
|
-
class Serializer
|
|
3
|
-
# Defines an association in the object should be rendered.
|
|
4
|
-
#
|
|
5
|
-
# The serializer object should implement the association name
|
|
6
|
-
# as a method which should return an array when invoked. If a method
|
|
7
|
-
# with the association name does not exist, the association name is
|
|
8
|
-
# dispatched to the serialized object.
|
|
9
|
-
#
|
|
10
|
-
module Associations
|
|
11
|
-
extend ActiveSupport::Concern
|
|
12
|
-
|
|
13
|
-
DEFAULT_INCLUDE_TREE = ActiveModel::Serializer::IncludeTree.from_string('*')
|
|
14
|
-
|
|
15
|
-
included do
|
|
16
|
-
with_options instance_writer: false, instance_reader: true do |serializer|
|
|
17
|
-
serializer.class_attribute :_reflections
|
|
18
|
-
self._reflections ||= []
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
extend ActiveSupport::Autoload
|
|
22
|
-
autoload :Association
|
|
23
|
-
autoload :Reflection
|
|
24
|
-
autoload :SingularReflection
|
|
25
|
-
autoload :CollectionReflection
|
|
26
|
-
autoload :BelongsToReflection
|
|
27
|
-
autoload :HasOneReflection
|
|
28
|
-
autoload :HasManyReflection
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
module ClassMethods
|
|
32
|
-
def inherited(base)
|
|
33
|
-
super
|
|
34
|
-
base._reflections = _reflections.dup
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
# @param [Symbol] name of the association
|
|
38
|
-
# @param [Hash<Symbol => any>] options for the reflection
|
|
39
|
-
# @return [void]
|
|
40
|
-
#
|
|
41
|
-
# @example
|
|
42
|
-
# has_many :comments, serializer: CommentSummarySerializer
|
|
43
|
-
#
|
|
44
|
-
def has_many(name, options = {}, &block)
|
|
45
|
-
associate(HasManyReflection.new(name, options, block))
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
# @param [Symbol] name of the association
|
|
49
|
-
# @param [Hash<Symbol => any>] options for the reflection
|
|
50
|
-
# @return [void]
|
|
51
|
-
#
|
|
52
|
-
# @example
|
|
53
|
-
# belongs_to :author, serializer: AuthorSerializer
|
|
54
|
-
#
|
|
55
|
-
def belongs_to(name, options = {}, &block)
|
|
56
|
-
associate(BelongsToReflection.new(name, options, block))
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
# @param [Symbol] name of the association
|
|
60
|
-
# @param [Hash<Symbol => any>] options for the reflection
|
|
61
|
-
# @return [void]
|
|
62
|
-
#
|
|
63
|
-
# @example
|
|
64
|
-
# has_one :author, serializer: AuthorSerializer
|
|
65
|
-
#
|
|
66
|
-
def has_one(name, options = {}, &block)
|
|
67
|
-
associate(HasOneReflection.new(name, options, block))
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
private
|
|
71
|
-
|
|
72
|
-
# Add reflection and define {name} accessor.
|
|
73
|
-
# @param [ActiveModel::Serializer::Reflection] reflection
|
|
74
|
-
# @return [void]
|
|
75
|
-
#
|
|
76
|
-
# @api private
|
|
77
|
-
#
|
|
78
|
-
def associate(reflection)
|
|
79
|
-
self._reflections << reflection
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
# @param [IncludeTree] include_tree (defaults to all associations when not provided)
|
|
84
|
-
# @return [Enumerator<Association>]
|
|
85
|
-
#
|
|
86
|
-
def associations(include_tree = DEFAULT_INCLUDE_TREE)
|
|
87
|
-
return unless object
|
|
88
|
-
|
|
89
|
-
Enumerator.new do |y|
|
|
90
|
-
self.class._reflections.each do |reflection|
|
|
91
|
-
next if reflection.excluded?(self)
|
|
92
|
-
key = reflection.options.fetch(:key, reflection.name)
|
|
93
|
-
next unless include_tree.key?(key)
|
|
94
|
-
y.yield reflection.build_association(self, instance_options)
|
|
95
|
-
end
|
|
96
|
-
end
|
|
97
|
-
end
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
end
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
module ActiveModel
|
|
2
|
-
class Serializer
|
|
3
|
-
module Attributes
|
|
4
|
-
extend ActiveSupport::Concern
|
|
5
|
-
|
|
6
|
-
included do
|
|
7
|
-
with_options instance_writer: false, instance_reader: false do |serializer|
|
|
8
|
-
serializer.class_attribute :_attributes_data # @api private
|
|
9
|
-
self._attributes_data ||= {}
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
extend ActiveSupport::Autoload
|
|
13
|
-
autoload :Attribute
|
|
14
|
-
|
|
15
|
-
# Return the +attributes+ of +object+ as presented
|
|
16
|
-
# by the serializer.
|
|
17
|
-
def attributes(requested_attrs = nil, reload = false)
|
|
18
|
-
@attributes = nil if reload
|
|
19
|
-
@attributes ||= self.class._attributes_data.each_with_object({}) do |(key, attr), hash|
|
|
20
|
-
next if attr.excluded?(self)
|
|
21
|
-
next unless requested_attrs.nil? || requested_attrs.include?(key)
|
|
22
|
-
hash[key] = attr.value(self)
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
module ClassMethods
|
|
28
|
-
def inherited(base)
|
|
29
|
-
super
|
|
30
|
-
base._attributes_data = _attributes_data.dup
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
# @example
|
|
34
|
-
# class AdminAuthorSerializer < ActiveModel::Serializer
|
|
35
|
-
# attributes :id, :name, :recent_edits
|
|
36
|
-
def attributes(*attrs)
|
|
37
|
-
attrs = attrs.first if attrs.first.class == Array
|
|
38
|
-
|
|
39
|
-
attrs.each do |attr|
|
|
40
|
-
attribute(attr)
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
# @example
|
|
45
|
-
# class AdminAuthorSerializer < ActiveModel::Serializer
|
|
46
|
-
# attributes :id, :recent_edits
|
|
47
|
-
# attribute :name, key: :title
|
|
48
|
-
#
|
|
49
|
-
# attribute :full_name do
|
|
50
|
-
# "#{object.first_name} #{object.last_name}"
|
|
51
|
-
# end
|
|
52
|
-
#
|
|
53
|
-
# def recent_edits
|
|
54
|
-
# object.edits.last(5)
|
|
55
|
-
# end
|
|
56
|
-
def attribute(attr, options = {}, &block)
|
|
57
|
-
key = options.fetch(:key, attr)
|
|
58
|
-
_attributes_data[key] = Attribute.new(attr, options, block)
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
# @api private
|
|
62
|
-
# keys of attributes
|
|
63
|
-
# @see Serializer::attribute
|
|
64
|
-
def _attributes
|
|
65
|
-
_attributes_data.keys
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
# @api private
|
|
69
|
-
# maps attribute value to explict key name
|
|
70
|
-
# @see Serializer::attribute
|
|
71
|
-
# @see FragmentCache#fragment_serializer
|
|
72
|
-
def _attributes_keys
|
|
73
|
-
_attributes_data
|
|
74
|
-
.each_with_object({}) do |(key, attr), hash|
|
|
75
|
-
next if key == attr.name
|
|
76
|
-
hash[attr.name] = { key: key }
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
end
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
module ActiveModel
|
|
2
|
-
class Serializer
|
|
3
|
-
module Configuration
|
|
4
|
-
include ActiveSupport::Configurable
|
|
5
|
-
extend ActiveSupport::Concern
|
|
6
|
-
|
|
7
|
-
# Configuration options may also be set in
|
|
8
|
-
# Serializers and Adapters
|
|
9
|
-
included do |base|
|
|
10
|
-
config = base.config
|
|
11
|
-
config.collection_serializer = ActiveModel::Serializer::CollectionSerializer
|
|
12
|
-
config.serializer_lookup_enabled = true
|
|
13
|
-
|
|
14
|
-
def config.array_serializer=(collection_serializer)
|
|
15
|
-
self.collection_serializer = collection_serializer
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def config.array_serializer
|
|
19
|
-
collection_serializer
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
config.adapter = :attributes
|
|
23
|
-
config.jsonapi_resource_type = :plural
|
|
24
|
-
config.jsonapi_version = '1.0'
|
|
25
|
-
config.jsonapi_toplevel_meta = {}
|
|
26
|
-
# Make JSON API top-level jsonapi member opt-in
|
|
27
|
-
# ref: http://jsonapi.org/format/#document-top-level
|
|
28
|
-
config.jsonapi_include_toplevel_object = false
|
|
29
|
-
config.key_transform = nil
|
|
30
|
-
|
|
31
|
-
config.schema_path = 'test/support/schemas'
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
module ActiveModel
|
|
2
|
-
class Serializer
|
|
3
|
-
# TODO: description of this class, and overview of how it's used
|
|
4
|
-
class IncludeTree
|
|
5
|
-
module Parsing
|
|
6
|
-
module_function
|
|
7
|
-
|
|
8
|
-
# Translates a comma separated list of dot separated paths (JSON API format) into a Hash.
|
|
9
|
-
#
|
|
10
|
-
# @example
|
|
11
|
-
# `'posts.author, posts.comments.upvotes, posts.comments.author'`
|
|
12
|
-
#
|
|
13
|
-
# would become
|
|
14
|
-
#
|
|
15
|
-
# `{ posts: { author: {}, comments: { author: {}, upvotes: {} } } }`.
|
|
16
|
-
#
|
|
17
|
-
# @param [String] included
|
|
18
|
-
# @return [Hash] a Hash representing the same tree structure
|
|
19
|
-
def include_string_to_hash(included)
|
|
20
|
-
# TODO: Needs comment walking through the process of what all this is doing.
|
|
21
|
-
included.delete(' ').split(',').reduce({}) do |hash, path|
|
|
22
|
-
include_tree = path.split('.').reverse_each.reduce({}) { |a, e| { e.to_sym => a } }
|
|
23
|
-
hash.deep_merge!(include_tree)
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
# Translates the arguments passed to the include option into a Hash. The format can be either
|
|
28
|
-
# a String (see #include_string_to_hash), an Array of Symbols and Hashes, or a mix of both.
|
|
29
|
-
#
|
|
30
|
-
# @example
|
|
31
|
-
# `posts: [:author, comments: [:author, :upvotes]]`
|
|
32
|
-
#
|
|
33
|
-
# would become
|
|
34
|
-
#
|
|
35
|
-
# `{ posts: { author: {}, comments: { author: {}, upvotes: {} } } }`.
|
|
36
|
-
#
|
|
37
|
-
# @example
|
|
38
|
-
# `[:author, :comments => [:author]]`
|
|
39
|
-
#
|
|
40
|
-
# would become
|
|
41
|
-
#
|
|
42
|
-
# `{:author => {}, :comments => { author: {} } }`
|
|
43
|
-
#
|
|
44
|
-
# @param [Symbol, Hash, Array, String] included
|
|
45
|
-
# @return [Hash] a Hash representing the same tree structure
|
|
46
|
-
def include_args_to_hash(included)
|
|
47
|
-
case included
|
|
48
|
-
when Symbol
|
|
49
|
-
{ included => {} }
|
|
50
|
-
when Hash
|
|
51
|
-
included.each_with_object({}) do |(key, value), hash|
|
|
52
|
-
hash[key] = include_args_to_hash(value)
|
|
53
|
-
end
|
|
54
|
-
when Array
|
|
55
|
-
included.reduce({}) { |a, e| a.deep_merge!(include_args_to_hash(e)) }
|
|
56
|
-
when String
|
|
57
|
-
include_string_to_hash(included)
|
|
58
|
-
else
|
|
59
|
-
{}
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
# Builds an IncludeTree from a comma separated list of dot separated paths (JSON API format).
|
|
65
|
-
# @example `'posts.author, posts.comments.upvotes, posts.comments.author'`
|
|
66
|
-
#
|
|
67
|
-
# @param [String] included
|
|
68
|
-
# @return [IncludeTree]
|
|
69
|
-
#
|
|
70
|
-
def self.from_string(included)
|
|
71
|
-
new(Parsing.include_string_to_hash(included))
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
# Translates the arguments passed to the include option into an IncludeTree.
|
|
75
|
-
# The format can be either a String (see #from_string), an Array of Symbols and Hashes, or a mix of both.
|
|
76
|
-
# @example `posts: [:author, comments: [:author, :upvotes]]`
|
|
77
|
-
#
|
|
78
|
-
# @param [Symbol, Hash, Array, String] included
|
|
79
|
-
# @return [IncludeTree]
|
|
80
|
-
#
|
|
81
|
-
def self.from_include_args(included)
|
|
82
|
-
return included if included.is_a?(IncludeTree)
|
|
83
|
-
|
|
84
|
-
new(Parsing.include_args_to_hash(included))
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
# @param [Hash] hash
|
|
88
|
-
def initialize(hash = {})
|
|
89
|
-
@hash = hash
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
def key?(key)
|
|
93
|
-
@hash.key?(key) || @hash.key?(:*) || @hash.key?(:**)
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
def [](key)
|
|
97
|
-
# TODO(beauby): Adopt a lazy caching strategy for generating subtrees.
|
|
98
|
-
case
|
|
99
|
-
when @hash.key?(key)
|
|
100
|
-
self.class.new(@hash[key])
|
|
101
|
-
when @hash.key?(:*)
|
|
102
|
-
self.class.new(@hash[:*])
|
|
103
|
-
when @hash.key?(:**)
|
|
104
|
-
self.class.new(:** => {})
|
|
105
|
-
else
|
|
106
|
-
nil
|
|
107
|
-
end
|
|
108
|
-
end
|
|
109
|
-
end
|
|
110
|
-
end
|
|
111
|
-
end
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
module ActiveModel
|
|
2
|
-
class Serializer
|
|
3
|
-
module Links
|
|
4
|
-
extend ActiveSupport::Concern
|
|
5
|
-
|
|
6
|
-
included do
|
|
7
|
-
with_options instance_writer: false, instance_reader: true do |serializer|
|
|
8
|
-
serializer.class_attribute :_links # @api private
|
|
9
|
-
self._links ||= {}
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
extend ActiveSupport::Autoload
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
module ClassMethods
|
|
16
|
-
def inherited(base)
|
|
17
|
-
super
|
|
18
|
-
base._links = _links.dup
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
# Define a link on a serializer.
|
|
22
|
-
# @example
|
|
23
|
-
# link(:self) { resource_url(object) }
|
|
24
|
-
# @example
|
|
25
|
-
# link(:self) { "http://example.com/resource/#{object.id}" }
|
|
26
|
-
# @example
|
|
27
|
-
# link :resource, "http://example.com/resource"
|
|
28
|
-
#
|
|
29
|
-
def link(name, value = nil, &block)
|
|
30
|
-
_links[name] = block || value
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
module ActiveModel
|
|
2
|
-
class Serializer
|
|
3
|
-
module Meta
|
|
4
|
-
extend ActiveSupport::Concern
|
|
5
|
-
|
|
6
|
-
included do
|
|
7
|
-
with_options instance_writer: false, instance_reader: true do |serializer|
|
|
8
|
-
serializer.class_attribute :_meta # @api private
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
extend ActiveSupport::Autoload
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
module ClassMethods
|
|
15
|
-
# Set the JSON API meta attribute of a serializer.
|
|
16
|
-
# @example
|
|
17
|
-
# class AdminAuthorSerializer < ActiveModel::Serializer
|
|
18
|
-
# meta { stuff: 'value' }
|
|
19
|
-
# @example
|
|
20
|
-
# meta do
|
|
21
|
-
# { comment_count: object.comments.count }
|
|
22
|
-
# end
|
|
23
|
-
def meta(value = nil, &block)
|
|
24
|
-
self._meta = block || value
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|