transmutation 0.2.3 → 0.3.0
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 +4 -0
- data/Gemfile.lock +1 -1
- data/lib/transmutation/serialization/lookup.rb +3 -9
- data/lib/transmutation/serialization/rendering.rb +3 -3
- data/lib/transmutation/serialization.rb +11 -3
- data/lib/transmutation/serializer.rb +83 -30
- data/lib/transmutation/version.rb +1 -1
- metadata +2 -3
- data/lib/transmutation/collection_serializer.rb +0 -31
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a1184809d63cb5abaad091e433a5e150579f5ca634a5522c57b7dd49c3465a3c
|
4
|
+
data.tar.gz: a0e2bddde883737a82369d14cd4bc75235ea1dee366c7a0234a262e29930a74c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ee23262517dba8436c182542b02bd3e1b15df0225b84eae7dedb106c4d155cf6dd78db791e9a98d44c57654dcf87d9aa8110e87cde6bface0943952199f8e2a5
|
7
|
+
data.tar.gz: 8b23bfbd305587fde6d6fef4a714840a73e4415d27902c3169dd06561f141b127944d64f13029a37f9aaf10d88bdab5b1059554ae132fc4584c899f6ecb3148e
|
data/.rubocop.yml
CHANGED
data/Gemfile.lock
CHANGED
@@ -12,9 +12,9 @@ module Transmutation
|
|
12
12
|
# Bubbles up the namespace until we find a matching serializer.
|
13
13
|
#
|
14
14
|
# @see Transmutation::Serialization#lookup_serializer
|
15
|
+
# @note This never bubbles up the object's namespace, only the caller's namespace.
|
15
16
|
#
|
16
|
-
#
|
17
|
-
#
|
17
|
+
# @example
|
18
18
|
# namespace: Api::V1::Admin::Detailed
|
19
19
|
# serializer: Chat::User
|
20
20
|
#
|
@@ -25,11 +25,7 @@ module Transmutation
|
|
25
25
|
# - Api::V1::Chat::UserSerializer
|
26
26
|
# - Api::Chat::UserSerializer
|
27
27
|
# - Chat::UserSerializer
|
28
|
-
#
|
29
|
-
# Note: This never bubbles up the object's namespace, only the caller's namespace.
|
30
28
|
def serializer_for(object, serializer: nil)
|
31
|
-
return Transmutation::CollectionSerializer if object.respond_to?(:map)
|
32
|
-
|
33
29
|
serializer_name = serializer_name_for(object, serializer: serializer)
|
34
30
|
|
35
31
|
return constantize_serializer!(Object, serializer_name, object: object) if serializer_name.start_with?("::")
|
@@ -38,7 +34,7 @@ module Transmutation
|
|
38
34
|
return potential_namespace.const_get(serializer_name) if potential_namespace.const_defined?(serializer_name)
|
39
35
|
end
|
40
36
|
|
41
|
-
raise SerializerNotFound.new(
|
37
|
+
raise SerializerNotFound.new(object, namespace: serializer_namespace, name: serializer_name)
|
42
38
|
end
|
43
39
|
|
44
40
|
# Returns the highest specificity serializer name for the given object.
|
@@ -47,8 +43,6 @@ module Transmutation
|
|
47
43
|
#
|
48
44
|
# @return [String] The serializer name.
|
49
45
|
def serializer_name_for(object, serializer: nil)
|
50
|
-
return "::Transmutation::CollectionSerializer" if object.respond_to?(:map)
|
51
|
-
|
52
46
|
"#{serializer&.delete_suffix("Serializer") || object.class.name}Serializer"
|
53
47
|
end
|
54
48
|
|
@@ -3,11 +3,11 @@
|
|
3
3
|
module Transmutation
|
4
4
|
module Serialization
|
5
5
|
module Rendering
|
6
|
-
def render(json: nil, serialize: true, **args)
|
6
|
+
def render(json: nil, serialize: true, namespace: nil, serializer: nil, max_depth: 1, **args)
|
7
7
|
return super(**args) unless json
|
8
|
-
return super(json: json
|
8
|
+
return super(**args, json: json) unless serialize
|
9
9
|
|
10
|
-
super(**args, json: serialize(json))
|
10
|
+
super(**args, json: serialize(json, namespace: namespace, serializer: serializer, max_depth: max_depth))
|
11
11
|
end
|
12
12
|
end
|
13
13
|
end
|
@@ -8,10 +8,18 @@ module Transmutation
|
|
8
8
|
# @param object [Object] The object to serialize.
|
9
9
|
# @param namespace [String, Symbol, Module] The namespace to lookup the serializer in.
|
10
10
|
# @param serializer [String, Symbol, Class] The serializer to use.
|
11
|
+
# @param max_depth [Integer] The maximum depth of nested associations to serialize.
|
11
12
|
#
|
12
13
|
# @return [Transmutation::Serializer] The serialized object. This will respond to `#as_json` and `#to_json`.
|
13
|
-
def serialize(object, namespace: nil, serializer: nil)
|
14
|
-
|
14
|
+
def serialize(object, namespace: nil, serializer: nil, depth: 0, max_depth: 1)
|
15
|
+
if object.respond_to?(:map)
|
16
|
+
return object.map do |item|
|
17
|
+
serialize(item, namespace: namespace, serializer: serializer, depth: depth, max_depth: max_depth)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
lookup_serializer(object, namespace: namespace, serializer: serializer)
|
22
|
+
.new(object, depth: depth, max_depth: max_depth)
|
15
23
|
end
|
16
24
|
|
17
25
|
# Lookup the serializer for the given object.
|
@@ -29,7 +37,7 @@ module Transmutation
|
|
29
37
|
end
|
30
38
|
|
31
39
|
private_class_method def self.included(base)
|
32
|
-
base.include(Rendering) if base.
|
40
|
+
base.include(Rendering) if base.method_defined?(:render)
|
33
41
|
end
|
34
42
|
end
|
35
43
|
end
|
@@ -10,12 +10,20 @@ module Transmutation
|
|
10
10
|
# attribute :full_name do
|
11
11
|
# "#{object.first_name} #{object.last_name}".strip
|
12
12
|
# end
|
13
|
+
#
|
14
|
+
# belongs_to :organization
|
15
|
+
#
|
16
|
+
# has_many :posts
|
13
17
|
# end
|
14
18
|
class Serializer
|
15
19
|
extend ClassAttributes
|
16
20
|
|
17
|
-
|
21
|
+
include Transmutation::Serialization
|
22
|
+
|
23
|
+
def initialize(object, depth: 0, max_depth: 1)
|
18
24
|
@object = object
|
25
|
+
@depth = depth
|
26
|
+
@max_depth = max_depth
|
19
27
|
end
|
20
28
|
|
21
29
|
def to_json(options = {})
|
@@ -24,39 +32,84 @@ module Transmutation
|
|
24
32
|
|
25
33
|
def as_json(_options = {})
|
26
34
|
attributes_config.each_with_object({}) do |(attr_name, attr_options), hash|
|
27
|
-
|
35
|
+
if attr_options[:association]
|
36
|
+
hash[attr_name.to_s] = instance_exec(&attr_options[:block]) if @depth + 1 <= @max_depth
|
37
|
+
else
|
38
|
+
hash[attr_name.to_s] = attr_options[:block] ? instance_exec(&attr_options[:block]) : object.send(attr_name)
|
39
|
+
end
|
28
40
|
end
|
29
41
|
end
|
30
42
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
43
|
+
class << self
|
44
|
+
# Define an attribute to be serialized
|
45
|
+
#
|
46
|
+
# @param attribute_name [Symbol] The name of the attribute to serialize
|
47
|
+
# @param block [Proc] The block to call to get the value of the attribute
|
48
|
+
# - The block is called in the context of the serializer instance
|
49
|
+
#
|
50
|
+
# @example
|
51
|
+
# class UserSerializer < Transmutation::Serializer
|
52
|
+
# attribute :first_name
|
53
|
+
#
|
54
|
+
# attribute :full_name do
|
55
|
+
# "#{object.first_name} #{object.last_name}".strip
|
56
|
+
# end
|
57
|
+
# end
|
58
|
+
def attribute(attribute_name, &block)
|
59
|
+
attributes_config[attribute_name] = { block: block }
|
60
|
+
end
|
61
|
+
|
62
|
+
# Define an association to be serialized
|
63
|
+
#
|
64
|
+
# @note By default, the serializer for the association is looked up in the same namespace as the serializer
|
65
|
+
#
|
66
|
+
# @param association_name [Symbol] The name of the association to serialize
|
67
|
+
# @param namespace [String, Symbol, Module] The namespace to lookup the association's serializer in
|
68
|
+
# @param serializer [String, Symbol, Class] The serializer to use for the association's serialization
|
69
|
+
#
|
70
|
+
# @example
|
71
|
+
# class UserSerializer < Transmutation::Serializer
|
72
|
+
# association :posts
|
73
|
+
# association :comments, namespace: "Nested", serializer: "User::CommentSerializer"
|
74
|
+
# end
|
75
|
+
def association(association_name, namespace: nil, serializer: nil)
|
76
|
+
block = lambda do
|
77
|
+
serialize(object.send(association_name), namespace: namespace, serializer: serializer, depth: @depth + 1)
|
78
|
+
end
|
79
|
+
|
80
|
+
attributes_config[association_name] = { block: block, association: true }
|
81
|
+
end
|
82
|
+
|
83
|
+
alias belongs_to association
|
84
|
+
alias has_one association
|
85
|
+
alias has_many association
|
86
|
+
|
87
|
+
# Shorthand for defining multiple attributes
|
88
|
+
#
|
89
|
+
# @param attribute_names [Array<Symbol>] The names of the attributes to serialize
|
90
|
+
#
|
91
|
+
# @example
|
92
|
+
# class UserSerializer < Transmutation::Serializer
|
93
|
+
# attributes :first_name, :last_name
|
94
|
+
# end
|
95
|
+
def attributes(*attribute_names)
|
96
|
+
attribute_names.each do |attribute_name|
|
97
|
+
attribute(attribute_name)
|
98
|
+
end
|
99
|
+
end
|
48
100
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
101
|
+
# Shorthand for defining multiple associations
|
102
|
+
#
|
103
|
+
# @param association_names [Array<Symbol>] The names of the associations to serialize
|
104
|
+
#
|
105
|
+
# @example
|
106
|
+
# class UserSerializer < Transmutation::Serializer
|
107
|
+
# associations :posts, :comments
|
108
|
+
# end
|
109
|
+
def associations(*association_names)
|
110
|
+
association_names.each do |association_name|
|
111
|
+
association(association_name)
|
112
|
+
end
|
60
113
|
end
|
61
114
|
end
|
62
115
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: transmutation
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- nitemaeric
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2024-06-
|
12
|
+
date: 2024-06-06 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: zeitwerk
|
@@ -46,7 +46,6 @@ files:
|
|
46
46
|
- Rakefile
|
47
47
|
- lib/transmutation.rb
|
48
48
|
- lib/transmutation/class_attributes.rb
|
49
|
-
- lib/transmutation/collection_serializer.rb
|
50
49
|
- lib/transmutation/serialization.rb
|
51
50
|
- lib/transmutation/serialization/lookup.rb
|
52
51
|
- lib/transmutation/serialization/lookup/serializer_not_found.rb
|
@@ -1,31 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Transmutation
|
4
|
-
# Out-of-the-box collection serializer.
|
5
|
-
#
|
6
|
-
# This serializer will be used to serialize all collections of objects.
|
7
|
-
#
|
8
|
-
# @example Basic usage
|
9
|
-
# Transmutation::CollectionSerializer.new([object, object]).to_json
|
10
|
-
class CollectionSerializer
|
11
|
-
include Transmutation::Serialization
|
12
|
-
|
13
|
-
def initialize(objects, namespace: nil, serializer: nil)
|
14
|
-
@objects = objects
|
15
|
-
@namespace = namespace
|
16
|
-
@serializer = serializer
|
17
|
-
end
|
18
|
-
|
19
|
-
def as_json(options = {})
|
20
|
-
objects.map { |item| serialize(item, namespace: namespace, serializer: serializer).as_json(options) }
|
21
|
-
end
|
22
|
-
|
23
|
-
def to_json(options = {})
|
24
|
-
as_json(options).to_json
|
25
|
-
end
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
|
-
attr_reader :objects, :namespace, :serializer
|
30
|
-
end
|
31
|
-
end
|