active_model_serializers 0.8.3 → 0.10.15
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 +726 -6
- data/{MIT-LICENSE.txt → MIT-LICENSE} +3 -2
- data/README.md +194 -545
- data/lib/action_controller/serialization.rb +53 -38
- data/lib/active_model/serializable_resource.rb +13 -0
- data/lib/active_model/serializer/adapter/attributes.rb +17 -0
- data/lib/active_model/serializer/adapter/base.rb +20 -0
- data/lib/active_model/serializer/adapter/json.rb +17 -0
- data/lib/active_model/serializer/adapter/json_api.rb +17 -0
- data/lib/active_model/serializer/adapter/null.rb +17 -0
- data/lib/active_model/serializer/adapter.rb +26 -0
- data/lib/active_model/serializer/array_serializer.rb +14 -0
- data/lib/active_model/serializer/association.rb +73 -0
- data/lib/active_model/serializer/attribute.rb +27 -0
- data/lib/active_model/serializer/belongs_to_reflection.rb +13 -0
- data/lib/active_model/serializer/collection_serializer.rb +99 -0
- data/lib/active_model/serializer/concerns/caching.rb +305 -0
- data/lib/active_model/serializer/error_serializer.rb +16 -0
- data/lib/active_model/serializer/errors_serializer.rb +34 -0
- data/lib/active_model/serializer/field.rb +92 -0
- data/lib/active_model/serializer/fieldset.rb +33 -0
- data/lib/active_model/serializer/has_many_reflection.rb +12 -0
- data/lib/active_model/serializer/has_one_reflection.rb +9 -0
- 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 +152 -0
- data/lib/active_model/serializer/null.rb +19 -0
- data/lib/active_model/serializer/reflection.rb +212 -0
- data/lib/active_model/serializer/version.rb +7 -0
- data/lib/active_model/serializer.rb +354 -442
- data/lib/active_model_serializers/adapter/attributes.rb +36 -0
- data/lib/active_model_serializers/adapter/base.rb +85 -0
- data/lib/active_model_serializers/adapter/json.rb +23 -0
- data/lib/active_model_serializers/adapter/json_api/deserialization.rb +215 -0
- data/lib/active_model_serializers/adapter/json_api/error.rb +98 -0
- data/lib/active_model_serializers/adapter/json_api/jsonapi.rb +51 -0
- data/lib/active_model_serializers/adapter/json_api/link.rb +85 -0
- data/lib/active_model_serializers/adapter/json_api/meta.rb +39 -0
- data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +94 -0
- data/lib/active_model_serializers/adapter/json_api/relationship.rb +106 -0
- data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +68 -0
- data/lib/active_model_serializers/adapter/json_api.rb +535 -0
- data/lib/active_model_serializers/adapter/null.rb +11 -0
- data/lib/active_model_serializers/adapter.rb +100 -0
- data/lib/active_model_serializers/callbacks.rb +57 -0
- data/lib/active_model_serializers/deprecate.rb +56 -0
- data/lib/active_model_serializers/deserialization.rb +17 -0
- data/lib/active_model_serializers/json_pointer.rb +16 -0
- data/lib/active_model_serializers/logging.rb +124 -0
- data/lib/active_model_serializers/lookup_chain.rb +82 -0
- data/lib/active_model_serializers/model.rb +132 -0
- data/lib/active_model_serializers/railtie.rb +62 -0
- data/lib/active_model_serializers/register_jsonapi_renderer.rb +80 -0
- data/lib/active_model_serializers/serializable_resource.rb +84 -0
- data/lib/active_model_serializers/serialization_context.rb +41 -0
- data/lib/active_model_serializers/test/schema.rb +140 -0
- data/lib/active_model_serializers/test/serializer.rb +127 -0
- data/lib/active_model_serializers/test.rb +9 -0
- data/lib/active_model_serializers.rb +49 -81
- data/lib/generators/rails/USAGE +6 -0
- data/lib/generators/rails/resource_override.rb +12 -0
- data/lib/generators/rails/serializer_generator.rb +38 -0
- data/lib/generators/rails/templates/serializer.rb.erb +8 -0
- data/lib/grape/active_model_serializers.rb +18 -0
- data/lib/grape/formatters/active_model_serializers.rb +34 -0
- data/lib/grape/helpers/active_model_serializers.rb +19 -0
- data/lib/tasks/rubocop.rake +60 -0
- metadata +240 -51
- data/.gitignore +0 -18
- data/.travis.yml +0 -28
- data/DESIGN.textile +0 -586
- data/Gemfile +0 -4
- data/Gemfile.edge +0 -9
- data/Rakefile +0 -18
- data/active_model_serializers.gemspec +0 -24
- data/bench/perf.rb +0 -43
- data/cruft.md +0 -19
- data/lib/active_model/array_serializer.rb +0 -104
- data/lib/active_model/serializer/associations.rb +0 -233
- data/lib/active_model/serializers/version.rb +0 -5
- data/lib/active_record/serializer_override.rb +0 -16
- data/lib/generators/resource_override.rb +0 -13
- data/lib/generators/serializer/USAGE +0 -9
- data/lib/generators/serializer/serializer_generator.rb +0 -42
- data/lib/generators/serializer/templates/serializer.rb +0 -19
- data/test/array_serializer_test.rb +0 -75
- data/test/association_test.rb +0 -592
- data/test/caching_test.rb +0 -96
- data/test/generators_test.rb +0 -85
- data/test/no_serialization_scope_test.rb +0 -34
- data/test/serialization_scope_name_test.rb +0 -67
- data/test/serialization_test.rb +0 -392
- data/test/serializer_support_test.rb +0 -51
- data/test/serializer_test.rb +0 -1465
- data/test/test_fakes.rb +0 -217
- data/test/test_helper.rb +0 -32
@@ -0,0 +1,94 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveModelSerializers
|
4
|
+
module Adapter
|
5
|
+
class JsonApi < Base
|
6
|
+
class PaginationLinks
|
7
|
+
MissingSerializationContextError = Class.new(KeyError)
|
8
|
+
FIRST_PAGE = 1
|
9
|
+
|
10
|
+
attr_reader :collection, :context
|
11
|
+
|
12
|
+
def initialize(collection, adapter_options)
|
13
|
+
@collection = collection
|
14
|
+
@adapter_options = adapter_options
|
15
|
+
@context = adapter_options.fetch(:serialization_context) do
|
16
|
+
fail MissingSerializationContextError, <<-EOF.freeze
|
17
|
+
JsonApi::PaginationLinks requires a ActiveModelSerializers::SerializationContext.
|
18
|
+
Please pass a ':serialization_context' option or
|
19
|
+
override CollectionSerializer#paginated? to return 'false'.
|
20
|
+
EOF
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def as_json
|
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
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
protected
|
35
|
+
|
36
|
+
attr_reader :adapter_options
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def location_url
|
41
|
+
url_for_page(collection.current_page)
|
42
|
+
end
|
43
|
+
|
44
|
+
def first_page_url
|
45
|
+
url_for_page(1)
|
46
|
+
end
|
47
|
+
|
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)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def prev_page_url
|
57
|
+
return nil if collection.current_page == FIRST_PAGE
|
58
|
+
if collection.current_page > collection.total_pages
|
59
|
+
return url_for_page(collection.total_pages)
|
60
|
+
end
|
61
|
+
url_for_page(collection.current_page - FIRST_PAGE)
|
62
|
+
end
|
63
|
+
|
64
|
+
def next_page_url
|
65
|
+
return nil if collection.total_pages == 0 ||
|
66
|
+
collection.current_page >= collection.total_pages
|
67
|
+
url_for_page(collection.next_page)
|
68
|
+
end
|
69
|
+
|
70
|
+
def url_for_page(number)
|
71
|
+
params = query_parameters.dup
|
72
|
+
params[:page] = { size: per_page, number: number }
|
73
|
+
"#{url(adapter_options)}?#{params.to_query}"
|
74
|
+
end
|
75
|
+
|
76
|
+
def url(options = {})
|
77
|
+
@url ||= options.fetch(:links, {}).fetch(:self, nil) || request_url
|
78
|
+
end
|
79
|
+
|
80
|
+
def request_url
|
81
|
+
@request_url ||= context.request_url
|
82
|
+
end
|
83
|
+
|
84
|
+
def query_parameters
|
85
|
+
@query_parameters ||= context.query_parameters
|
86
|
+
end
|
87
|
+
|
88
|
+
def per_page
|
89
|
+
@per_page ||= collection.try(:per_page) || collection.try(:limit_value) || collection.size
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveModelSerializers
|
4
|
+
module Adapter
|
5
|
+
class JsonApi
|
6
|
+
class Relationship
|
7
|
+
# {http://jsonapi.org/format/#document-resource-object-related-resource-links Document Resource Object Related Resource Links}
|
8
|
+
# {http://jsonapi.org/format/#document-links Document Links}
|
9
|
+
# {http://jsonapi.org/format/#document-resource-object-linkage Document Resource Relationship Linkage}
|
10
|
+
# {http://jsonapi.org/format/#document-meta Document Meta}
|
11
|
+
def initialize(parent_serializer, serializable_resource_options, association)
|
12
|
+
@parent_serializer = parent_serializer
|
13
|
+
@association = association
|
14
|
+
@serializable_resource_options = serializable_resource_options
|
15
|
+
end
|
16
|
+
|
17
|
+
def as_json
|
18
|
+
hash = {}
|
19
|
+
|
20
|
+
hash[:data] = data_for(association) if association.include_data?
|
21
|
+
|
22
|
+
links = links_for(association)
|
23
|
+
hash[:links] = links if links.any?
|
24
|
+
|
25
|
+
meta = meta_for(association)
|
26
|
+
hash[:meta] = meta if meta
|
27
|
+
hash[:meta] = {} if hash.empty?
|
28
|
+
|
29
|
+
hash
|
30
|
+
end
|
31
|
+
|
32
|
+
protected
|
33
|
+
|
34
|
+
attr_reader :parent_serializer, :serializable_resource_options, :association
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
# TODO(BF): Avoid db hit on belong_to_ releationship by using foreign_key on self
|
39
|
+
def data_for(association)
|
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)
|
80
|
+
virtual_value
|
81
|
+
else
|
82
|
+
[]
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def links_for(association)
|
87
|
+
association.links.each_with_object({}) do |(key, value), hash|
|
88
|
+
result = Link.new(parent_serializer, value).as_json
|
89
|
+
hash[key] = result if result
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def meta_for(association)
|
94
|
+
meta = association.meta
|
95
|
+
meta.respond_to?(:call) ? parent_serializer.instance_eval(&meta) : meta
|
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
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveModelSerializers
|
4
|
+
module Adapter
|
5
|
+
class JsonApi
|
6
|
+
class ResourceIdentifier
|
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
|
17
|
+
else
|
18
|
+
{ id: id.to_s, type: type }
|
19
|
+
end
|
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)
|
35
|
+
end
|
36
|
+
|
37
|
+
# {http://jsonapi.org/format/#document-resource-identifier-objects Resource Identifier Objects}
|
38
|
+
def initialize(serializer, options)
|
39
|
+
@id = id_for(serializer)
|
40
|
+
@type = type_for(serializer, options)
|
41
|
+
end
|
42
|
+
|
43
|
+
def as_json
|
44
|
+
if id.blank?
|
45
|
+
{ type: type }
|
46
|
+
else
|
47
|
+
{ id: id.to_s, type: type }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
protected
|
52
|
+
|
53
|
+
attr_reader :id, :type
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def type_for(serializer, transform_options)
|
58
|
+
serializer_type = serializer._type
|
59
|
+
self.class.type_for(serializer, serializer_type, transform_options)
|
60
|
+
end
|
61
|
+
|
62
|
+
def id_for(serializer)
|
63
|
+
serializer.read_attribute_for_serialization(:id).to_s
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|