active_model_serializers 0.10.3 → 0.10.12
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/CHANGELOG.md +154 -2
- data/README.md +153 -15
- data/lib/action_controller/serialization.rb +11 -1
- data/lib/active_model/serializable_resource.rb +2 -0
- data/lib/active_model/serializer.rb +275 -81
- data/lib/active_model/serializer/adapter.rb +2 -0
- data/lib/active_model/serializer/adapter/attributes.rb +2 -0
- data/lib/active_model/serializer/adapter/base.rb +2 -0
- data/lib/active_model/serializer/adapter/json.rb +2 -0
- data/lib/active_model/serializer/adapter/json_api.rb +2 -0
- data/lib/active_model/serializer/adapter/null.rb +2 -0
- data/lib/active_model/serializer/array_serializer.rb +2 -0
- data/lib/active_model/serializer/association.rb +53 -14
- data/lib/active_model/serializer/attribute.rb +2 -0
- data/lib/active_model/serializer/belongs_to_reflection.rb +7 -1
- data/lib/active_model/serializer/collection_serializer.rb +8 -5
- data/lib/active_model/serializer/concerns/caching.rb +36 -23
- data/lib/active_model/serializer/error_serializer.rb +2 -0
- data/lib/active_model/serializer/errors_serializer.rb +2 -0
- data/lib/active_model/serializer/field.rb +2 -0
- data/lib/active_model/serializer/fieldset.rb +3 -1
- data/lib/active_model/serializer/has_many_reflection.rb +6 -1
- data/lib/active_model/serializer/has_one_reflection.rb +3 -1
- data/lib/active_model/serializer/lazy_association.rb +99 -0
- data/lib/active_model/serializer/link.rb +23 -0
- data/lib/active_model/serializer/lint.rb +2 -0
- data/lib/active_model/serializer/null.rb +2 -0
- data/lib/active_model/serializer/reflection.rb +122 -73
- data/lib/active_model/serializer/version.rb +3 -1
- data/lib/active_model_serializers.rb +29 -11
- data/lib/active_model_serializers/adapter.rb +3 -1
- data/lib/active_model_serializers/adapter/attributes.rb +23 -0
- data/lib/active_model_serializers/adapter/base.rb +4 -2
- data/lib/active_model_serializers/adapter/json.rb +2 -0
- data/lib/active_model_serializers/adapter/json_api.rb +44 -26
- data/lib/active_model_serializers/adapter/json_api/deserialization.rb +4 -2
- data/lib/active_model_serializers/adapter/json_api/error.rb +2 -0
- data/lib/active_model_serializers/adapter/json_api/jsonapi.rb +2 -0
- data/lib/active_model_serializers/adapter/json_api/link.rb +2 -0
- data/lib/active_model_serializers/adapter/json_api/meta.rb +2 -0
- data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +42 -21
- data/lib/active_model_serializers/adapter/json_api/relationship.rb +52 -9
- data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +35 -18
- data/lib/active_model_serializers/adapter/null.rb +2 -0
- data/lib/active_model_serializers/callbacks.rb +2 -0
- data/lib/active_model_serializers/deprecate.rb +2 -0
- data/lib/active_model_serializers/deserialization.rb +2 -0
- data/lib/active_model_serializers/json_pointer.rb +2 -0
- data/lib/active_model_serializers/logging.rb +2 -0
- data/lib/active_model_serializers/lookup_chain.rb +2 -0
- data/lib/active_model_serializers/model.rb +111 -30
- data/lib/active_model_serializers/model/caching.rb +25 -0
- data/lib/active_model_serializers/railtie.rb +4 -0
- data/lib/active_model_serializers/register_jsonapi_renderer.rb +2 -0
- data/lib/active_model_serializers/serializable_resource.rb +4 -2
- data/lib/active_model_serializers/serialization_context.rb +2 -0
- data/lib/active_model_serializers/test.rb +2 -0
- data/lib/active_model_serializers/test/schema.rb +4 -2
- data/lib/active_model_serializers/test/serializer.rb +2 -0
- data/lib/generators/rails/resource_override.rb +3 -1
- data/lib/generators/rails/serializer_generator.rb +2 -0
- data/lib/grape/active_model_serializers.rb +2 -0
- data/lib/grape/formatters/active_model_serializers.rb +2 -0
- data/lib/grape/helpers/active_model_serializers.rb +2 -0
- data/lib/tasks/rubocop.rake +55 -0
- metadata +74 -291
- data/.github/ISSUE_TEMPLATE.md +0 -29
- data/.github/PULL_REQUEST_TEMPLATE.md +0 -15
- data/.gitignore +0 -35
- data/.rubocop.yml +0 -102
- data/.simplecov +0 -110
- data/.travis.yml +0 -51
- data/CODE_OF_CONDUCT.md +0 -74
- data/CONTRIBUTING.md +0 -105
- data/Gemfile +0 -56
- data/Rakefile +0 -103
- data/active_model_serializers.gemspec +0 -62
- data/appveyor.yml +0 -24
- data/bin/bench +0 -171
- data/bin/bench_regression +0 -316
- data/bin/serve_benchmark +0 -39
- data/docs/ARCHITECTURE.md +0 -125
- data/docs/README.md +0 -42
- data/docs/STYLE.md +0 -58
- data/docs/general/adapters.md +0 -247
- data/docs/general/caching.md +0 -58
- data/docs/general/configuration_options.md +0 -169
- data/docs/general/deserialization.md +0 -100
- data/docs/general/fields.md +0 -31
- data/docs/general/getting_started.md +0 -133
- data/docs/general/instrumentation.md +0 -40
- data/docs/general/key_transforms.md +0 -40
- data/docs/general/logging.md +0 -14
- data/docs/general/rendering.md +0 -294
- data/docs/general/serializers.md +0 -461
- data/docs/how-open-source-maintained.jpg +0 -0
- data/docs/howto/add_pagination_links.md +0 -138
- data/docs/howto/add_relationship_links.md +0 -137
- data/docs/howto/add_root_key.md +0 -55
- data/docs/howto/grape_integration.md +0 -42
- data/docs/howto/outside_controller_use.md +0 -65
- data/docs/howto/passing_arbitrary_options.md +0 -27
- data/docs/howto/serialize_poro.md +0 -32
- data/docs/howto/test.md +0 -154
- data/docs/howto/upgrade_from_0_8_to_0_10.md +0 -265
- data/docs/integrations/ember-and-json-api.md +0 -144
- data/docs/integrations/grape.md +0 -19
- data/docs/jsonapi/errors.md +0 -56
- data/docs/jsonapi/schema.md +0 -151
- data/docs/jsonapi/schema/schema.json +0 -366
- data/docs/rfcs/0000-namespace.md +0 -106
- data/docs/rfcs/template.md +0 -15
- data/lib/active_model/serializer/collection_reflection.rb +0 -7
- data/lib/active_model/serializer/concerns/associations.rb +0 -102
- data/lib/active_model/serializer/concerns/attributes.rb +0 -82
- data/lib/active_model/serializer/concerns/configuration.rb +0 -59
- data/lib/active_model/serializer/concerns/links.rb +0 -35
- data/lib/active_model/serializer/concerns/meta.rb +0 -29
- data/lib/active_model/serializer/concerns/type.rb +0 -25
- data/lib/active_model/serializer/singular_reflection.rb +0 -7
- data/lib/active_model_serializers/key_transform.rb +0 -74
- data/test/action_controller/adapter_selector_test.rb +0 -53
- data/test/action_controller/explicit_serializer_test.rb +0 -135
- data/test/action_controller/json/include_test.rb +0 -246
- data/test/action_controller/json_api/deserialization_test.rb +0 -112
- data/test/action_controller/json_api/errors_test.rb +0 -40
- data/test/action_controller/json_api/fields_test.rb +0 -57
- data/test/action_controller/json_api/linked_test.rb +0 -202
- data/test/action_controller/json_api/pagination_test.rb +0 -116
- data/test/action_controller/json_api/transform_test.rb +0 -181
- data/test/action_controller/lookup_proc_test.rb +0 -49
- data/test/action_controller/namespace_lookup_test.rb +0 -226
- data/test/action_controller/serialization_scope_name_test.rb +0 -229
- data/test/action_controller/serialization_test.rb +0 -472
- data/test/active_model_serializers/adapter_for_test.rb +0 -208
- data/test/active_model_serializers/json_pointer_test.rb +0 -22
- data/test/active_model_serializers/key_transform_test.rb +0 -297
- data/test/active_model_serializers/logging_test.rb +0 -77
- data/test/active_model_serializers/model_test.rb +0 -22
- data/test/active_model_serializers/railtie_test_isolated.rb +0 -63
- data/test/active_model_serializers/register_jsonapi_renderer_test_isolated.rb +0 -143
- data/test/active_model_serializers/serialization_context_test_isolated.rb +0 -71
- data/test/active_model_serializers/test/schema_test.rb +0 -130
- data/test/active_model_serializers/test/serializer_test.rb +0 -62
- data/test/active_record_test.rb +0 -9
- data/test/adapter/attributes_test.rb +0 -43
- data/test/adapter/deprecation_test.rb +0 -100
- data/test/adapter/json/belongs_to_test.rb +0 -45
- data/test/adapter/json/collection_test.rb +0 -104
- data/test/adapter/json/has_many_test.rb +0 -45
- data/test/adapter/json/transform_test.rb +0 -93
- data/test/adapter/json_api/belongs_to_test.rb +0 -155
- data/test/adapter/json_api/collection_test.rb +0 -96
- data/test/adapter/json_api/errors_test.rb +0 -76
- data/test/adapter/json_api/fields_test.rb +0 -88
- data/test/adapter/json_api/has_many_embed_ids_test.rb +0 -43
- data/test/adapter/json_api/has_many_explicit_serializer_test.rb +0 -96
- data/test/adapter/json_api/has_many_test.rb +0 -165
- data/test/adapter/json_api/has_one_test.rb +0 -80
- data/test/adapter/json_api/include_data_if_sideloaded_test.rb +0 -166
- data/test/adapter/json_api/json_api_test.rb +0 -33
- data/test/adapter/json_api/linked_test.rb +0 -413
- data/test/adapter/json_api/links_test.rb +0 -95
- data/test/adapter/json_api/pagination_links_test.rb +0 -193
- data/test/adapter/json_api/parse_test.rb +0 -137
- data/test/adapter/json_api/relationship_test.rb +0 -397
- data/test/adapter/json_api/resource_identifier_test.rb +0 -110
- data/test/adapter/json_api/resource_meta_test.rb +0 -100
- data/test/adapter/json_api/toplevel_jsonapi_test.rb +0 -82
- data/test/adapter/json_api/transform_test.rb +0 -504
- data/test/adapter/json_api/type_test.rb +0 -61
- data/test/adapter/json_test.rb +0 -46
- data/test/adapter/null_test.rb +0 -22
- data/test/adapter/polymorphic_test.rb +0 -171
- data/test/adapter_test.rb +0 -67
- data/test/array_serializer_test.rb +0 -22
- data/test/benchmark/app.rb +0 -65
- data/test/benchmark/benchmarking_support.rb +0 -67
- data/test/benchmark/bm_active_record.rb +0 -81
- data/test/benchmark/bm_adapter.rb +0 -38
- data/test/benchmark/bm_caching.rb +0 -119
- data/test/benchmark/bm_lookup_chain.rb +0 -83
- data/test/benchmark/bm_transform.rb +0 -45
- data/test/benchmark/config.ru +0 -3
- data/test/benchmark/controllers.rb +0 -83
- data/test/benchmark/fixtures.rb +0 -219
- data/test/cache_test.rb +0 -579
- data/test/collection_serializer_test.rb +0 -110
- data/test/fixtures/active_record.rb +0 -78
- data/test/fixtures/poro.rb +0 -286
- data/test/generators/scaffold_controller_generator_test.rb +0 -24
- data/test/generators/serializer_generator_test.rb +0 -74
- data/test/grape_test.rb +0 -178
- data/test/lint_test.rb +0 -49
- data/test/logger_test.rb +0 -20
- data/test/poro_test.rb +0 -9
- data/test/serializable_resource_test.rb +0 -79
- data/test/serializers/association_macros_test.rb +0 -37
- data/test/serializers/associations_test.rb +0 -370
- data/test/serializers/attribute_test.rb +0 -151
- data/test/serializers/attributes_test.rb +0 -52
- data/test/serializers/caching_configuration_test_isolated.rb +0 -170
- data/test/serializers/configuration_test.rb +0 -32
- data/test/serializers/fieldset_test.rb +0 -14
- data/test/serializers/meta_test.rb +0 -202
- data/test/serializers/options_test.rb +0 -21
- data/test/serializers/read_attribute_for_serialization_test.rb +0 -79
- data/test/serializers/root_test.rb +0 -21
- data/test/serializers/serialization_test.rb +0 -55
- data/test/serializers/serializer_for_test.rb +0 -136
- data/test/serializers/serializer_for_with_namespace_test.rb +0 -87
- data/test/support/custom_schemas/active_model_serializers/test/schema_test/my/index.json +0 -6
- data/test/support/isolated_unit.rb +0 -82
- data/test/support/rails5_shims.rb +0 -53
- data/test/support/rails_app.rb +0 -36
- data/test/support/schemas/active_model_serializers/test/schema_test/my/index.json +0 -6
- data/test/support/schemas/active_model_serializers/test/schema_test/my/show.json +0 -6
- data/test/support/schemas/custom/show.json +0 -7
- data/test/support/schemas/hyper_schema.json +0 -93
- data/test/support/schemas/render_using_json_api.json +0 -43
- data/test/support/schemas/simple_json_pointers.json +0 -10
- data/test/support/serialization_testing.rb +0 -71
- data/test/test_helper.rb +0 -58
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ActiveModelSerializers
|
|
2
4
|
module Adapter
|
|
3
5
|
class JsonApi
|
|
@@ -189,7 +191,7 @@ module ActiveModelSerializers
|
|
|
189
191
|
|
|
190
192
|
polymorphic = (options[:polymorphic] || []).include?(assoc_name.to_sym)
|
|
191
193
|
if polymorphic
|
|
192
|
-
hash["#{prefix_key}_type".to_sym] = assoc_data.present? ? assoc_data['type'] : nil
|
|
194
|
+
hash["#{prefix_key}_type".to_sym] = assoc_data.present? ? assoc_data['type'].classify : nil
|
|
193
195
|
end
|
|
194
196
|
|
|
195
197
|
hash
|
|
@@ -205,7 +207,7 @@ module ActiveModelSerializers
|
|
|
205
207
|
# @api private
|
|
206
208
|
def transform_keys(hash, options)
|
|
207
209
|
transform = options[:key_transform] || :underscore
|
|
208
|
-
|
|
210
|
+
CaseTransform.send(transform, hash)
|
|
209
211
|
end
|
|
210
212
|
end
|
|
211
213
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ActiveModelSerializers
|
|
2
4
|
module Adapter
|
|
3
5
|
class JsonApi < Base
|
|
@@ -15,17 +17,18 @@ module ActiveModelSerializers
|
|
|
15
17
|
JsonApi::PaginationLinks requires a ActiveModelSerializers::SerializationContext.
|
|
16
18
|
Please pass a ':serialization_context' option or
|
|
17
19
|
override CollectionSerializer#paginated? to return 'false'.
|
|
18
|
-
|
|
20
|
+
EOF
|
|
19
21
|
end
|
|
20
22
|
end
|
|
21
23
|
|
|
22
24
|
def as_json
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
{
|
|
26
|
+
self: location_url,
|
|
27
|
+
first: first_page_url,
|
|
28
|
+
prev: prev_page_url,
|
|
29
|
+
next: next_page_url,
|
|
30
|
+
last: last_page_url
|
|
31
|
+
}
|
|
29
32
|
end
|
|
30
33
|
|
|
31
34
|
protected
|
|
@@ -34,25 +37,39 @@ module ActiveModelSerializers
|
|
|
34
37
|
|
|
35
38
|
private
|
|
36
39
|
|
|
37
|
-
def
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
{}.tap do |pages|
|
|
41
|
-
pages[:self] = collection.current_page
|
|
40
|
+
def location_url
|
|
41
|
+
url_for_page(collection.current_page)
|
|
42
|
+
end
|
|
42
43
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
end
|
|
44
|
+
def first_page_url
|
|
45
|
+
url_for_page(1)
|
|
46
|
+
end
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
def last_page_url
|
|
49
|
+
if collection.total_pages == 0
|
|
50
|
+
url_for_page(FIRST_PAGE)
|
|
51
|
+
else
|
|
52
|
+
url_for_page(collection.total_pages)
|
|
52
53
|
end
|
|
53
54
|
end
|
|
54
55
|
|
|
55
|
-
def
|
|
56
|
+
def prev_page_url
|
|
57
|
+
return nil if collection.current_page == FIRST_PAGE
|
|
58
|
+
url_for_page(collection.current_page - FIRST_PAGE)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def next_page_url
|
|
62
|
+
return nil if collection.total_pages == 0 || collection.current_page == collection.total_pages
|
|
63
|
+
url_for_page(collection.next_page)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def url_for_page(number)
|
|
67
|
+
params = query_parameters.dup
|
|
68
|
+
params[:page] = { size: per_page, number: number }
|
|
69
|
+
"#{url(adapter_options)}?#{params.to_query}"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def url(options = {})
|
|
56
73
|
@url ||= options.fetch(:links, {}).fetch(:self, nil) || request_url
|
|
57
74
|
end
|
|
58
75
|
|
|
@@ -63,6 +80,10 @@ module ActiveModelSerializers
|
|
|
63
80
|
def query_parameters
|
|
64
81
|
@query_parameters ||= context.query_parameters
|
|
65
82
|
end
|
|
83
|
+
|
|
84
|
+
def per_page
|
|
85
|
+
@per_page ||= collection.try(:per_page) || collection.try(:limit_value) || collection.size
|
|
86
|
+
end
|
|
66
87
|
end
|
|
67
88
|
end
|
|
68
89
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ActiveModelSerializers
|
|
2
4
|
module Adapter
|
|
3
5
|
class JsonApi
|
|
@@ -15,9 +17,7 @@ module ActiveModelSerializers
|
|
|
15
17
|
def as_json
|
|
16
18
|
hash = {}
|
|
17
19
|
|
|
18
|
-
if association.
|
|
19
|
-
hash[:data] = data_for(association)
|
|
20
|
-
end
|
|
20
|
+
hash[:data] = data_for(association) if association.include_data?
|
|
21
21
|
|
|
22
22
|
links = links_for(association)
|
|
23
23
|
hash[:links] = links if links.any?
|
|
@@ -35,14 +35,51 @@ module ActiveModelSerializers
|
|
|
35
35
|
|
|
36
36
|
private
|
|
37
37
|
|
|
38
|
+
# TODO(BF): Avoid db hit on belong_to_ releationship by using foreign_key on self
|
|
38
39
|
def data_for(association)
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
if association.collection?
|
|
41
|
+
data_for_many(association)
|
|
42
|
+
else
|
|
43
|
+
data_for_one(association)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def data_for_one(association)
|
|
48
|
+
if belongs_to_id_on_self?(association)
|
|
49
|
+
id = parent_serializer.read_attribute_for_serialization(association.reflection.foreign_key)
|
|
50
|
+
type =
|
|
51
|
+
if association.polymorphic?
|
|
52
|
+
# We can't infer resource type for polymorphic relationships from the serializer.
|
|
53
|
+
# We can ONLY know a polymorphic resource type by inspecting each resource.
|
|
54
|
+
association.lazy_association.serializer.json_key
|
|
55
|
+
else
|
|
56
|
+
association.reflection.type.to_s
|
|
57
|
+
end
|
|
58
|
+
ResourceIdentifier.for_type_with_id(type, id, serializable_resource_options)
|
|
59
|
+
else
|
|
60
|
+
# TODO(BF): Process relationship without evaluating lazy_association
|
|
61
|
+
serializer = association.lazy_association.serializer
|
|
62
|
+
if (virtual_value = association.virtual_value)
|
|
63
|
+
virtual_value
|
|
64
|
+
elsif serializer && association.object
|
|
65
|
+
ResourceIdentifier.new(serializer, serializable_resource_options).as_json
|
|
66
|
+
else
|
|
67
|
+
nil
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def data_for_many(association)
|
|
73
|
+
# TODO(BF): Process relationship without evaluating lazy_association
|
|
74
|
+
collection_serializer = association.lazy_association.serializer
|
|
75
|
+
if collection_serializer.respond_to?(:each)
|
|
76
|
+
collection_serializer.map do |serializer|
|
|
77
|
+
ResourceIdentifier.new(serializer, serializable_resource_options).as_json
|
|
78
|
+
end
|
|
79
|
+
elsif (virtual_value = association.virtual_value)
|
|
43
80
|
virtual_value
|
|
44
|
-
|
|
45
|
-
|
|
81
|
+
else
|
|
82
|
+
[]
|
|
46
83
|
end
|
|
47
84
|
end
|
|
48
85
|
|
|
@@ -57,6 +94,12 @@ module ActiveModelSerializers
|
|
|
57
94
|
meta = association.meta
|
|
58
95
|
meta.respond_to?(:call) ? parent_serializer.instance_eval(&meta) : meta
|
|
59
96
|
end
|
|
97
|
+
|
|
98
|
+
def belongs_to_id_on_self?(association)
|
|
99
|
+
parent_serializer.config.jsonapi_use_foreign_key_on_belongs_to_relationship &&
|
|
100
|
+
association.belongs_to? &&
|
|
101
|
+
parent_serializer.object.respond_to?(association.reflection.foreign_key)
|
|
102
|
+
end
|
|
60
103
|
end
|
|
61
104
|
end
|
|
62
105
|
end
|
|
@@ -1,25 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ActiveModelSerializers
|
|
2
4
|
module Adapter
|
|
3
5
|
class JsonApi
|
|
4
6
|
class ResourceIdentifier
|
|
5
|
-
def self.type_for(
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
def self.type_for(serializer, serializer_type = nil, transform_options = {})
|
|
8
|
+
raw_type = serializer_type ? serializer_type : raw_type_from_serializer_object(serializer.object)
|
|
9
|
+
JsonApi.send(:transform_key_casing!, raw_type, transform_options)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.for_type_with_id(type, id, options)
|
|
13
|
+
type = inflect_type(type)
|
|
14
|
+
type = type_for(:no_class_needed, type, options)
|
|
15
|
+
if id.blank?
|
|
16
|
+
nil
|
|
8
17
|
else
|
|
9
|
-
|
|
10
|
-
if ActiveModelSerializers.config.jsonapi_resource_type == :singular
|
|
11
|
-
:singularize
|
|
12
|
-
else
|
|
13
|
-
:pluralize
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
raw_type = class_name.underscore
|
|
17
|
-
raw_type = ActiveSupport::Inflector.public_send(inflection, raw_type)
|
|
18
|
-
raw_type
|
|
19
|
-
.gsub!('/'.freeze, ActiveModelSerializers.config.jsonapi_namespace_separator)
|
|
20
|
-
raw_type
|
|
18
|
+
{ id: id.to_s, type: type }
|
|
21
19
|
end
|
|
22
|
-
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.raw_type_from_serializer_object(object)
|
|
23
|
+
class_name = object.class.name # should use model_name
|
|
24
|
+
raw_type = class_name.underscore
|
|
25
|
+
raw_type = inflect_type(raw_type)
|
|
26
|
+
raw_type
|
|
27
|
+
.gsub!('/'.freeze, ActiveModelSerializers.config.jsonapi_namespace_separator)
|
|
28
|
+
raw_type
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def self.inflect_type(type)
|
|
32
|
+
singularize = ActiveModelSerializers.config.jsonapi_resource_type == :singular
|
|
33
|
+
inflection = singularize ? :singularize : :pluralize
|
|
34
|
+
ActiveSupport::Inflector.public_send(inflection, type)
|
|
23
35
|
end
|
|
24
36
|
|
|
25
37
|
# {http://jsonapi.org/format/#document-resource-identifier-objects Resource Identifier Objects}
|
|
@@ -29,7 +41,11 @@ module ActiveModelSerializers
|
|
|
29
41
|
end
|
|
30
42
|
|
|
31
43
|
def as_json
|
|
32
|
-
|
|
44
|
+
if id.blank?
|
|
45
|
+
{ type: type }
|
|
46
|
+
else
|
|
47
|
+
{ id: id.to_s, type: type }
|
|
48
|
+
end
|
|
33
49
|
end
|
|
34
50
|
|
|
35
51
|
protected
|
|
@@ -39,7 +55,8 @@ module ActiveModelSerializers
|
|
|
39
55
|
private
|
|
40
56
|
|
|
41
57
|
def type_for(serializer, transform_options)
|
|
42
|
-
|
|
58
|
+
serializer_type = serializer._type
|
|
59
|
+
self.class.type_for(serializer, serializer_type, transform_options)
|
|
43
60
|
end
|
|
44
61
|
|
|
45
62
|
def id_for(serializer)
|
|
@@ -1,51 +1,132 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
#
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# ActiveModelSerializers::Model is a convenient superclass for making your models
|
|
4
|
+
# from Plain-Old Ruby Objects (PORO). It also serves as a reference implementation
|
|
5
|
+
# that satisfies ActiveModel::Serializer::Lint::Tests.
|
|
6
|
+
require 'active_support/core_ext/hash'
|
|
4
7
|
module ActiveModelSerializers
|
|
5
8
|
class Model
|
|
6
|
-
include ActiveModel::Model
|
|
7
9
|
include ActiveModel::Serializers::JSON
|
|
10
|
+
include ActiveModel::Model
|
|
8
11
|
|
|
9
|
-
|
|
12
|
+
# Declare names of attributes to be included in +attributes+ hash.
|
|
13
|
+
# Is only available as a class-method since the ActiveModel::Serialization mixin in Rails
|
|
14
|
+
# uses an +attribute_names+ local variable, which may conflict if we were to add instance methods here.
|
|
15
|
+
#
|
|
16
|
+
# @overload attribute_names
|
|
17
|
+
# @return [Array<Symbol>]
|
|
18
|
+
class_attribute :attribute_names, instance_writer: false, instance_reader: false
|
|
19
|
+
# Initialize +attribute_names+ for all subclasses. The array is usually
|
|
20
|
+
# mutated in the +attributes+ method, but can be set directly, as well.
|
|
21
|
+
self.attribute_names = []
|
|
10
22
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
23
|
+
# Easily declare instance attributes with setters and getters for each.
|
|
24
|
+
#
|
|
25
|
+
# To initialize an instance, all attributes must have setters.
|
|
26
|
+
# However, the hash returned by +attributes+ instance method will ALWAYS
|
|
27
|
+
# be the value of the initial attributes, regardless of what accessors are defined.
|
|
28
|
+
# The only way to change the change the attributes after initialization is
|
|
29
|
+
# to mutate the +attributes+ directly.
|
|
30
|
+
# Accessor methods do NOT mutate the attributes. (This is a bug).
|
|
31
|
+
#
|
|
32
|
+
# @note For now, the Model only supports the notion of 'attributes'.
|
|
33
|
+
# In the tests, there is a special Model that also supports 'associations'. This is
|
|
34
|
+
# important so that we can add accessors for values that should not appear in the
|
|
35
|
+
# attributes hash when modeling associations. It is not yet clear if it
|
|
36
|
+
# makes sense for a PORO to have associations outside of the tests.
|
|
37
|
+
#
|
|
38
|
+
# @overload attributes(names)
|
|
39
|
+
# @param names [Array<String, Symbol>]
|
|
40
|
+
# @param name [String, Symbol]
|
|
41
|
+
def self.attributes(*names)
|
|
42
|
+
self.attribute_names |= names.map(&:to_sym)
|
|
43
|
+
# Silence redefinition of methods warnings
|
|
44
|
+
ActiveModelSerializers.silence_warnings do
|
|
45
|
+
attr_accessor(*names)
|
|
46
|
+
end
|
|
15
47
|
end
|
|
16
48
|
|
|
17
|
-
#
|
|
18
|
-
def
|
|
19
|
-
|
|
49
|
+
# Opt-in to breaking change
|
|
50
|
+
def self.derive_attributes_from_names_and_fix_accessors
|
|
51
|
+
unless included_modules.include?(DeriveAttributesFromNamesAndFixAccessors)
|
|
52
|
+
prepend(DeriveAttributesFromNamesAndFixAccessors)
|
|
53
|
+
end
|
|
20
54
|
end
|
|
21
55
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
56
|
+
module DeriveAttributesFromNamesAndFixAccessors
|
|
57
|
+
def self.included(base)
|
|
58
|
+
# NOTE that +id+ will always be in +attributes+.
|
|
59
|
+
base.attributes :id
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Override the +attributes+ method so that the hash is derived from +attribute_names+.
|
|
63
|
+
#
|
|
64
|
+
# The fields in +attribute_names+ determines the returned hash.
|
|
65
|
+
# +attributes+ are returned frozen to prevent any expectations that mutation affects
|
|
66
|
+
# the actual values in the model.
|
|
67
|
+
def attributes
|
|
68
|
+
self.class.attribute_names.each_with_object({}) do |attribute_name, result|
|
|
69
|
+
result[attribute_name] = public_send(attribute_name).freeze
|
|
70
|
+
end.with_indifferent_access.freeze
|
|
71
|
+
end
|
|
25
72
|
end
|
|
26
73
|
|
|
27
|
-
#
|
|
28
|
-
|
|
29
|
-
|
|
74
|
+
# Support for validation and other ActiveModel::Errors
|
|
75
|
+
# @return [ActiveModel::Errors]
|
|
76
|
+
attr_reader :errors
|
|
77
|
+
|
|
78
|
+
# (see #updated_at)
|
|
79
|
+
attr_writer :updated_at
|
|
80
|
+
|
|
81
|
+
# The only way to change the attributes of an instance is to directly mutate the attributes.
|
|
82
|
+
# @example
|
|
83
|
+
#
|
|
84
|
+
# model.attributes[:foo] = :bar
|
|
85
|
+
# @return [Hash]
|
|
86
|
+
attr_reader :attributes
|
|
87
|
+
|
|
88
|
+
# @param attributes [Hash]
|
|
89
|
+
def initialize(attributes = {})
|
|
90
|
+
attributes ||= {} # protect against nil
|
|
91
|
+
@attributes = attributes.symbolize_keys.with_indifferent_access
|
|
92
|
+
@errors = ActiveModel::Errors.new(self)
|
|
93
|
+
super
|
|
30
94
|
end
|
|
31
95
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
96
|
+
# Defaults to the downcased model name.
|
|
97
|
+
# This probably isn't a good default, since it's not a unique instance identifier,
|
|
98
|
+
# but that's what is currently implemented \_('-')_/.
|
|
99
|
+
#
|
|
100
|
+
# @note Though +id+ is defined, it will only show up
|
|
101
|
+
# in +attributes+ when it is passed in to the initializer or added to +attributes+,
|
|
102
|
+
# such as <tt>attributes[:id] = 5</tt>.
|
|
103
|
+
# @return [String, Numeric, Symbol]
|
|
104
|
+
def id
|
|
105
|
+
attributes.fetch(:id) do
|
|
106
|
+
defined?(@id) ? @id : self.class.model_name.name && self.class.model_name.name.downcase
|
|
37
107
|
end
|
|
38
108
|
end
|
|
39
109
|
|
|
40
|
-
#
|
|
41
|
-
#
|
|
42
|
-
|
|
43
|
-
|
|
110
|
+
# When not set, defaults to the time the file was modified.
|
|
111
|
+
#
|
|
112
|
+
# @note Though +updated_at+ and +updated_at=+ are defined, it will only show up
|
|
113
|
+
# in +attributes+ when it is passed in to the initializer or added to +attributes+,
|
|
114
|
+
# such as <tt>attributes[:updated_at] = Time.current</tt>.
|
|
115
|
+
# @return [String, Numeric, Time]
|
|
116
|
+
def updated_at
|
|
117
|
+
attributes.fetch(:updated_at) do
|
|
118
|
+
defined?(@updated_at) ? @updated_at : File.mtime(__FILE__)
|
|
119
|
+
end
|
|
44
120
|
end
|
|
45
121
|
|
|
46
|
-
|
|
47
|
-
|
|
122
|
+
# To customize model behavior, this method must be redefined. However,
|
|
123
|
+
# there are other ways of setting the +cache_key+ a serializer uses.
|
|
124
|
+
# @return [String]
|
|
125
|
+
def cache_key
|
|
126
|
+
ActiveSupport::Cache.expand_cache_key([
|
|
127
|
+
self.class.model_name.name.downcase,
|
|
128
|
+
"#{id}-#{updated_at.strftime('%Y%m%d%H%M%S%9N')}"
|
|
129
|
+
].compact)
|
|
48
130
|
end
|
|
49
|
-
# :nocov:
|
|
50
131
|
end
|
|
51
132
|
end
|