simply_serializable 1.2.2 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b0f8989f2a8520c25271107350edf070e2274d1fb17c48068f7c90394a907df4
4
- data.tar.gz: 9a65b5876a365b43b469e874a9429524e2dd5685207376e3ee4541bcf3c59047
3
+ metadata.gz: ed7754c68910d4556534b53f8475b8c36d1ad9259408508523c3bbd5463d0157
4
+ data.tar.gz: 39eb74d95beb65aee78582fba369bbe5bd76ef082ad9d5a5cedf28f5d738ceb3
5
5
  SHA512:
6
- metadata.gz: 5e7ea38a315a6d758ec707c99216f61b860252a47fbf0c93fa700967b331a0cefd9d3686b5397605322310d87e6b2dc4880ec7f6354139afbb0b43f0a514d700
7
- data.tar.gz: 2485f4b6be1560e14644fc6bfc03be00e65d6690202d3237af00f3ac0b6e0b2722a175cc1decbda2c106cd4870b7deef4f104b5c5bb879a991681e659e49d084
6
+ metadata.gz: 90156f91281bb1fdf486351962b3380ee430866feea4418f2644d72e07d4f60c3346459b7125e81e3141bdcd488e626be0aa4f9572782a9eb1b3dbd6d6f09f03
7
+ data.tar.gz: 455a807775db2e60c18f670e2c8ed080cd8995d3164c356e33897919c3af71315c26d21cdd038831f07246ca1c22acb1fe3873db1803d72f69420665392c0ab9
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- simply_serializable (1.2.2)
4
+ simply_serializable (1.3.0)
5
5
  fingerprintable (>= 1.2.1)
6
6
 
7
7
  GEM
@@ -35,13 +35,15 @@ module SimplySerializable
35
35
  base.extend(ClassMethods)
36
36
  end
37
37
 
38
- def serialize(cache: {})
39
- serializer(cache: cache).serialize
38
+ def serialize(cache: {}, **options)
39
+ serializer(cache: cache, **options).serialize
40
40
  end
41
41
 
42
- def serializer(cache: {})
42
+ def serializer(cache: {}, **options)
43
43
  Serializer.new(
44
44
  **self.class.serializable_config.merge(
45
+ options
46
+ ).merge(
45
47
  cache: cache,
46
48
  object: self
47
49
  )
@@ -49,11 +51,7 @@ module SimplySerializable
49
51
  end
50
52
 
51
53
  def serializable_id
52
- "#{serializable_type}/#{fingerprint}"
53
- end
54
-
55
- def serializable_type
56
- self.class.name
54
+ serializer.id
57
55
  end
58
56
  end
59
57
  end
@@ -17,47 +17,57 @@ module SimplySerializable
17
17
  only: nil
18
18
  )
19
19
  @object = object
20
+ @id = id
20
21
  @attributes = attributes
21
22
  @include_readable_instance_variables = include_readable_instance_variables
22
23
  @except = except&.map(&:to_sym)
23
24
  @only = only&.map(&:to_sym)
24
25
  @method_prefix = method_prefix
25
- @cache = cache
26
- @cache[cache_key] = nil
27
- @serialized = false
26
+ @local_cache = cache
27
+ @local_cache[cache_key] = nil
28
28
 
29
29
  populate_attributes
30
30
  end
31
31
 
32
32
  def cache
33
- serialize unless @serialized
34
- @cache
33
+ @cache ||= begin
34
+ serialize
35
+ @local_cache
36
+ end
35
37
  end
36
38
 
37
- def deep_serialize(obj)
38
- case obj
39
- when FalseClass, Float, nil, Integer, String, Symbol, TrueClass
40
- obj
41
- when Array
42
- obj.map { |v| deep_serialize(v) }
43
- when Hash
44
- Hash[obj.map { |k, v| [deep_serialize(k), deep_serialize(v)] }]
45
- when Module
46
- obj.name
47
- else
48
- serialize_object(obj)
39
+ def id
40
+ @id ||= cache_key
41
+ end
42
+
43
+ def nestable?
44
+ return @nestable unless @nestable.nil?
45
+
46
+ serialize
47
+ @nestable
48
+ end
49
+
50
+ def nested
51
+ @nested ||= begin
52
+ deep_nest(serialize[:root])
49
53
  end
50
54
  end
51
55
 
52
56
  def serialize
53
57
  @serialize ||= begin
54
- @serialized = true
58
+ @nestable = true
55
59
  ret = deep_serialize(object_value_hash)
56
60
 
57
- cache[cache_key] = ret
61
+ @local_cache[cache_key] = {
62
+ id: cache_key,
63
+ object: object.class.name,
64
+ fingeprint: fingerprint,
65
+ data: ret
66
+ }
67
+
58
68
  {
59
69
  root: cache_key,
60
- objects: cache
70
+ objects: @local_cache
61
71
  }
62
72
  end
63
73
  end
@@ -68,6 +78,50 @@ module SimplySerializable
68
78
 
69
79
  private
70
80
 
81
+ def cache_key
82
+ @cache_key ||= cache_key_for(object)
83
+ end
84
+
85
+ def cache_key_for(obj)
86
+ "#{obj.class.name}/#{fingerprint_for(obj)}"
87
+ end
88
+
89
+ def deep_nest(obj_id)
90
+ raise Error::CircularDependencyError unless @nestable
91
+
92
+ Hash[@local_cache[obj_id][:data].map do |k, v|
93
+ v = deep_nest(v.dig(:id)) if v.is_a?(Hash) && v.dig(:object) == :reference
94
+ [k, v]
95
+ end]
96
+ end
97
+
98
+ def deep_serialize(obj)
99
+ case obj
100
+ when FalseClass, Float, nil, Integer, String, Symbol, TrueClass
101
+ obj
102
+ when Array
103
+ obj.map { |v| deep_serialize(v) }
104
+ when Hash
105
+ Hash[obj.map { |k, v| [deep_serialize(k), deep_serialize(v)] }]
106
+ when Module
107
+ obj.name
108
+ else
109
+ serialize_object(obj)
110
+ end
111
+ end
112
+
113
+ def fingerprint
114
+ @fingerprint ||= fingerprint_for(object)
115
+ end
116
+
117
+ def fingerprint_for(obj)
118
+ if obj.respond_to?(:fingerprint)
119
+ obj.fingerprint
120
+ else
121
+ Fingerprintable::Fingerprinter.new(object: obj).fingerprint
122
+ end
123
+ end
124
+
71
125
  def instance_vars_with_readers
72
126
  instance_variables = Hash[object.instance_variables.map { |e| [e, 1] }]
73
127
  ret = object.class.instance_methods.select do |method|
@@ -76,18 +130,18 @@ module SimplySerializable
76
130
  ret.map(&:to_sym)
77
131
  end
78
132
 
79
- def serialize_object(use_object)
80
- use_object_cache_key = cache_key(use_object)
81
- return use_object_cache_key if cache.key?(use_object_cache_key)
82
- raise "#{use_object.class.name} does not respond to serialize. Did you mean to include Serializable in this class?" unless use_object.respond_to?(:serialize)
83
-
84
- serializer = use_object.serializer(cache: cache)
85
- cache.merge!(serializer.cache)
86
- use_object_cache_key
133
+ def method_for_attribute(attr)
134
+ if object.class.instance_methods.include?("#{@method_prefix}_#{attr}".to_sym)
135
+ "#{@method_prefix}_#{attr}"
136
+ else
137
+ attr
138
+ end
87
139
  end
88
140
 
89
- def cache_key(obj = object)
90
- obj.serializable_id
141
+ def object_value_hash
142
+ Hash[attributes.map do |attr|
143
+ [attr, object.send(method_for_attribute(attr))]
144
+ end]
91
145
  end
92
146
 
93
147
  def populate_attributes
@@ -100,18 +154,32 @@ module SimplySerializable
100
154
  attributes
101
155
  end
102
156
 
103
- def method_for_attribute(attr)
104
- if object.class.instance_methods.include?("#{@method_prefix}_#{attr}".to_sym)
105
- "#{@method_prefix}_#{attr}"
106
- else
107
- attr
157
+ def serialize_object(use_object)
158
+ use_object_cache_key = cache_key_for(use_object)
159
+ if @local_cache.key?(use_object_cache_key)
160
+ @nestable = false
161
+ return reference_to(use_object_cache_key)
108
162
  end
163
+ serializer = unless use_object.respond_to?(:serialize)
164
+ raise "#{use_object.class.name} does not respond to serialize. Did you mean to include Serializable in this class?" unless @include_readable_instance_variables
165
+
166
+ Serializer.new(
167
+ cache: @local_cache,
168
+ object: use_object
169
+ )
170
+ else
171
+ use_object.serializer(cache: @local_cache)
172
+ end
173
+ serializer
174
+ @local_cache.merge!(serializer.cache)
175
+ reference_to(use_object_cache_key)
109
176
  end
110
177
 
111
- def object_value_hash
112
- Hash[attributes.map do |attr|
113
- [attr, object.send(method_for_attribute(attr))]
114
- end]
178
+ def reference_to(key)
179
+ {
180
+ object: :reference,
181
+ id: key
182
+ }
115
183
  end
116
184
  end
117
185
  end
@@ -1,3 +1,3 @@
1
1
  module SimplySerializable
2
- VERSION = "1.2.2"
2
+ VERSION = "1.3.0"
3
3
  end
@@ -4,4 +4,22 @@ require "simply_serializable/version"
4
4
  require "simply_serializable/serializer"
5
5
  require "simply_serializable/mixin"
6
6
 
7
- module SimplySerializable; end
7
+ module SimplySerializable
8
+ class Error < StandardError
9
+ attr_reader :type
10
+
11
+ def initialize(message, type:)
12
+ @type = type
13
+ super(message)
14
+ end
15
+
16
+ class CircularDependencyError < Error
17
+ def initialize
18
+ super(
19
+ 'Circular dependency detected',
20
+ type: :circular_dependency
21
+ )
22
+ end
23
+ end
24
+ end
25
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simply_serializable
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.2
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Jackson
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-06-17 00:00:00.000000000 Z
11
+ date: 2019-06-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fingerprintable
@@ -103,7 +103,6 @@ executables: []
103
103
  extensions: []
104
104
  extra_rdoc_files: []
105
105
  files:
106
- - ".byebug_history"
107
106
  - ".gitignore"
108
107
  - ".rspec"
109
108
  - ".travis.yml"
data/.byebug_history DELETED
@@ -1,21 +0,0 @@
1
- exit
2
- c
3
- serializable_config
4
- n
5
- serializable_config
6
- attributes
7
- c
8
- attributes
9
- pdb
10
- c
11
- attributes
12
- n
13
- except
14
- n
15
- only
16
- attributes
17
- n
18
- attributes
19
- n
20
- instance_vars_with_readers
21
- attributes