store_model 4.5.0 → 4.6.1
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/README.md +4 -1
- data/lib/store_model/configuration.rb +7 -0
- data/lib/store_model/ext/active_record/base.rb +16 -5
- data/lib/store_model/ext/parent_assignment.rb +4 -1
- data/lib/store_model/model.rb +13 -3
- data/lib/store_model/nested_attributes.rb +1 -1
- data/lib/store_model/types/one.rb +1 -1
- data/lib/store_model/types/one_of.rb +3 -2
- data/lib/store_model/types/one_polymorphic.rb +16 -2
- data/lib/store_model/version.rb +1 -1
- data/lib/store_model.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c20c6465ee84ba2d0ffce4610ea14b6f6fed01e5da08cda8b165392e1d2e2952
|
|
4
|
+
data.tar.gz: 072ca921fd0b02814fc917b5d2c6b2df14f8c3bd99c536fda472b5df64ea7774
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a2e4339119a3076c4d200a535267033045d0fe75b461c2dfbe9b8d95bae1b4ecff0634ea5cbc5786076029fa2aba8027ac8a70e4f9d465c750f5f4d3a404b237
|
|
7
|
+
data.tar.gz: 1c8e8941a81e46a1f4d082a59252fc7867bcb95684a814a17701121e69ae82005fb0ca21da2dd3fea49467d3048c0c51ea0661c9d92b706573ce4a7e265c3eb5
|
data/README.md
CHANGED
|
@@ -22,7 +22,10 @@ class Product < ApplicationRecord
|
|
|
22
22
|
end
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
## Professional Support
|
|
26
|
+
|
|
27
|
+
Working on a complex Rails application and need an experienced eye?
|
|
28
|
+
I'm available for consulting — [get in touch](https://dmitrytsepelev.dev/consulting).
|
|
26
29
|
|
|
27
30
|
## Why should I wrap my JSON columns?
|
|
28
31
|
|
|
@@ -39,12 +39,19 @@ module StoreModel
|
|
|
39
39
|
# @return [Boolean]
|
|
40
40
|
attr_accessor :active_admin_compatibility
|
|
41
41
|
|
|
42
|
+
# Controls whether nested attributes updates preserve existing model instances by default.
|
|
43
|
+
# When true, acts like `update_only: true` for all singular nested attributes unless overridden.
|
|
44
|
+
# Default: false
|
|
45
|
+
# @return [Boolean]
|
|
46
|
+
attr_accessor :nested_attributes_update_only
|
|
47
|
+
|
|
42
48
|
def initialize
|
|
43
49
|
@serialize_unknown_attributes = true
|
|
44
50
|
@enable_parent_assignment = true
|
|
45
51
|
@serialize_enums_using_as_json = true
|
|
46
52
|
@serialize_empty_attributes = true
|
|
47
53
|
@active_admin_compatibility = false
|
|
54
|
+
@nested_attributes_update_only = false
|
|
48
55
|
end
|
|
49
56
|
end
|
|
50
57
|
end
|
|
@@ -8,14 +8,25 @@ module StoreModel
|
|
|
8
8
|
include ParentAssignment
|
|
9
9
|
|
|
10
10
|
def _read_attribute(*)
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
value = super
|
|
12
|
+
assign_parent_to_store_model_relation(value) if store_model_attribute?(value)
|
|
13
|
+
value
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def _write_attribute(*)
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
value = super
|
|
18
|
+
assign_parent_to_store_model_relation(value) if store_model_attribute?(value)
|
|
19
|
+
value
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def store_model_attribute?(value)
|
|
25
|
+
case value
|
|
26
|
+
when StoreModel::Model then true
|
|
27
|
+
when Array then value.first.is_a?(StoreModel::Model)
|
|
28
|
+
when Hash then value.each_value.any? { |v| v.is_a?(StoreModel::Model) }
|
|
29
|
+
else false
|
|
19
30
|
end
|
|
20
31
|
end
|
|
21
32
|
end
|
data/lib/store_model/model.rb
CHANGED
|
@@ -216,7 +216,10 @@ module StoreModel
|
|
|
216
216
|
#
|
|
217
217
|
# @return [Hash]
|
|
218
218
|
def unknown_attributes
|
|
219
|
-
@unknown_attributes
|
|
219
|
+
return @unknown_attributes if defined?(@unknown_attributes)
|
|
220
|
+
return {}.freeze if frozen?
|
|
221
|
+
|
|
222
|
+
@unknown_attributes = {}
|
|
220
223
|
end
|
|
221
224
|
|
|
222
225
|
# Returns the value of the `@serialize_unknown_attributes` instance
|
|
@@ -291,10 +294,13 @@ module StoreModel
|
|
|
291
294
|
end
|
|
292
295
|
|
|
293
296
|
def serialized_attribute(attr)
|
|
294
|
-
|
|
297
|
+
case attr.value
|
|
298
|
+
when StoreModel::Model
|
|
295
299
|
Types::RawJSONEncoder.new(attr.value_for_database)
|
|
296
|
-
|
|
300
|
+
when Array
|
|
297
301
|
serialize_array_attribute(attr.value)
|
|
302
|
+
when Hash # attribute :smth, json
|
|
303
|
+
attr.value
|
|
298
304
|
else
|
|
299
305
|
attr.value_for_database
|
|
300
306
|
end
|
|
@@ -314,6 +320,10 @@ module StoreModel
|
|
|
314
320
|
return unless Array(attr.value).all? { |value| value.is_a?(StoreModel::Model) }
|
|
315
321
|
|
|
316
322
|
Array(attr.value).each do |value|
|
|
323
|
+
# Skip frozen objects - they cannot have instance variables modified
|
|
324
|
+
# but will still serialize correctly with their existing settings
|
|
325
|
+
next if value.frozen?
|
|
326
|
+
|
|
317
327
|
value.serialize_unknown_attributes = serialize_unknown_attributes
|
|
318
328
|
value.serialize_enums_using_as_json = serialize_enums_using_as_json
|
|
319
329
|
value.serialize_empty_attributes = serialize_empty_attributes
|
|
@@ -50,7 +50,7 @@ module StoreModel
|
|
|
50
50
|
|
|
51
51
|
attributes.each do |attribute|
|
|
52
52
|
if nested_attribute_type(attribute).is_a?(Types::Base)
|
|
53
|
-
options.reverse_merge!(allow_destroy: false, update_only:
|
|
53
|
+
options.reverse_merge!(allow_destroy: false, update_only: StoreModel.config.nested_attributes_update_only)
|
|
54
54
|
define_store_model_attr_accessors(attribute, options)
|
|
55
55
|
else
|
|
56
56
|
super(*attribute, options)
|
|
@@ -74,7 +74,7 @@ module StoreModel
|
|
|
74
74
|
case value
|
|
75
75
|
when String
|
|
76
76
|
payload = ActiveSupport::JSON.decode(value) rescue {}
|
|
77
|
-
model_instance(deserialize_by_types(payload))
|
|
77
|
+
model_instance(deserialize_by_types(payload)) unless payload.nil?
|
|
78
78
|
when ::Hash
|
|
79
79
|
model_instance(deserialize_by_types(value))
|
|
80
80
|
when nil
|
|
@@ -7,12 +7,13 @@ module StoreModel
|
|
|
7
7
|
# Implements ActiveModel::Type::Value type for handling an array of
|
|
8
8
|
# StoreModel::Model
|
|
9
9
|
class OneOf
|
|
10
|
-
def initialize(&block)
|
|
10
|
+
def initialize(union: false, &block)
|
|
11
11
|
@block = block
|
|
12
|
+
@union = union
|
|
12
13
|
end
|
|
13
14
|
|
|
14
15
|
def to_type
|
|
15
|
-
Types::OnePolymorphic.new(@block)
|
|
16
|
+
Types::OnePolymorphic.new(@block, union: @union)
|
|
16
17
|
end
|
|
17
18
|
|
|
18
19
|
def to_array_type
|
|
@@ -13,8 +13,9 @@ module StoreModel
|
|
|
13
13
|
# @param model_wrapper [Proc] class to handle
|
|
14
14
|
#
|
|
15
15
|
# @return [StoreModel::Types::OnePolymorphic ]
|
|
16
|
-
def initialize(model_wrapper)
|
|
16
|
+
def initialize(model_wrapper, union: false)
|
|
17
17
|
@model_wrapper = model_wrapper
|
|
18
|
+
@union = union
|
|
18
19
|
super()
|
|
19
20
|
end
|
|
20
21
|
|
|
@@ -30,8 +31,9 @@ module StoreModel
|
|
|
30
31
|
# @param value [Object] a value to cast
|
|
31
32
|
#
|
|
32
33
|
# @return StoreModel::Model
|
|
33
|
-
def cast_value(value) # rubocop:disable Metrics/MethodLength
|
|
34
|
+
def cast_value(value) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
34
35
|
return nil if value.nil?
|
|
36
|
+
return nil if @union && value.respond_to?(:empty?) && value.empty?
|
|
35
37
|
|
|
36
38
|
if value.is_a?(String)
|
|
37
39
|
decode_and_initialize(value)
|
|
@@ -87,6 +89,18 @@ module StoreModel
|
|
|
87
89
|
"Hash or instances which implement StoreModel::Model are allowed"
|
|
88
90
|
end
|
|
89
91
|
|
|
92
|
+
# rubocop:disable Style/RescueModifier
|
|
93
|
+
def decode_and_initialize(value)
|
|
94
|
+
decoded = ActiveSupport::JSON.decode(value) rescue nil
|
|
95
|
+
return nil if decoded.nil?
|
|
96
|
+
return nil if @union && decoded.respond_to?(:empty?) && decoded.empty?
|
|
97
|
+
|
|
98
|
+
model_instance(decoded)
|
|
99
|
+
rescue ActiveModel::UnknownAttributeError => e
|
|
100
|
+
handle_unknown_attribute(decoded, e)
|
|
101
|
+
end
|
|
102
|
+
# rubocop:enable Style/RescueModifier
|
|
103
|
+
|
|
90
104
|
def model_instance(value)
|
|
91
105
|
extract_model_klass(value).new(value)
|
|
92
106
|
end
|
data/lib/store_model/version.rb
CHANGED
data/lib/store_model.rb
CHANGED
|
@@ -58,7 +58,7 @@ module StoreModel # :nodoc:
|
|
|
58
58
|
end
|
|
59
59
|
|
|
60
60
|
def union_one_of(discriminator, class_map)
|
|
61
|
-
Types::OneOf.new do |attributes|
|
|
61
|
+
Types::OneOf.new(union: true) do |attributes|
|
|
62
62
|
next nil unless attributes
|
|
63
63
|
|
|
64
64
|
discriminator_value = attributes.with_indifferent_access[discriminator]
|