attr_json 0.2.0 → 1.5.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 +5 -5
- data/.github/workflows/ci.yml +87 -0
- data/.github/workflows/future_rails_ci.yml +66 -0
- data/.gitignore +1 -0
- data/Appraisals +62 -0
- data/CHANGELOG.md +67 -0
- data/Gemfile +38 -35
- data/README.md +161 -36
- data/attr_json.gemspec +27 -4
- data/doc_src/dirty_tracking.md +1 -1
- data/doc_src/forms.md +76 -14
- data/gemfiles/.bundle/config +2 -0
- data/gemfiles/rails_5_0.gemfile +20 -0
- data/gemfiles/rails_5_1.gemfile +19 -0
- data/gemfiles/rails_5_2.gemfile +19 -0
- data/gemfiles/rails_6_0.gemfile +19 -0
- data/gemfiles/rails_6_1.gemfile +19 -0
- data/gemfiles/rails_7_0.gemfile +19 -0
- data/gemfiles/rails_edge.gemfile +19 -0
- data/lib/attr_json/attribute_definition/registry.rb +6 -1
- data/lib/attr_json/attribute_definition.rb +15 -2
- data/lib/attr_json/config.rb +55 -0
- data/lib/attr_json/model.rb +125 -42
- data/lib/attr_json/nested_attributes/writer.rb +26 -1
- data/lib/attr_json/nested_attributes.rb +7 -1
- data/lib/attr_json/record/dirty.rb +19 -13
- data/lib/attr_json/record/query_builder.rb +15 -3
- data/lib/attr_json/record/query_scopes.rb +6 -0
- data/lib/attr_json/record.rb +120 -32
- data/lib/attr_json/serialization_coder_from_type.rb +40 -0
- data/lib/attr_json/type/array.rb +6 -0
- data/lib/attr_json/type/container_attribute.rb +14 -3
- data/lib/attr_json/type/model.rb +38 -8
- data/lib/attr_json/type/polymorphic_model.rb +7 -0
- data/lib/attr_json/version.rb +1 -1
- data/lib/attr_json.rb +1 -1
- metadata +61 -21
- data/.travis.yml +0 -17
data/lib/attr_json/record.rb
CHANGED
@@ -17,21 +17,83 @@ module AttrJson
|
|
17
17
|
module Record
|
18
18
|
extend ActiveSupport::Concern
|
19
19
|
|
20
|
-
DEFAULT_CONTAINER_ATTRIBUTE = :json_attributes
|
21
|
-
|
22
20
|
included do
|
23
|
-
unless self
|
21
|
+
unless self <= ActiveRecord::Base
|
24
22
|
raise TypeError, "AttrJson::Record can only be used with an ActiveRecord::Base model. #{self} does not appear to be one. Are you looking for ::AttrJson::Model?"
|
25
23
|
end
|
26
24
|
|
27
25
|
class_attribute :attr_json_registry, instance_accessor: false
|
28
26
|
self.attr_json_registry = AttrJson::AttributeDefinition::Registry.new
|
27
|
+
end
|
29
28
|
|
30
|
-
|
31
|
-
|
29
|
+
protected
|
30
|
+
|
31
|
+
# adapted from ActiveRecord query_attribute method
|
32
|
+
# https://github.com/rails/rails/blob/v5.2.3/activerecord/lib/active_record/attribute_methods/query.rb#L12
|
33
|
+
#
|
34
|
+
# Sadly we could not re-use Rails code here, becuase the built-in method assumes attribute
|
35
|
+
# can be obtained with `self[attr_name]`, which you can not with attr_json (is that bad?), as
|
36
|
+
# well as `self.class.columns_hash[attr_name]` which you definitely can not (which is probably not bad),
|
37
|
+
# and has no way to use the value-translation semantics independently of that. May be a problem if
|
38
|
+
# ActiveRecord changes it's query method semantics in the future, will have to be sync'd here.
|
39
|
+
#
|
40
|
+
# Used to implement query methods on attr_json attributes, like `attr_json :foo, :string`, method `#foo?`
|
41
|
+
def self.attr_json_query_method(record, attribute)
|
42
|
+
value = record.send(attribute)
|
43
|
+
|
44
|
+
case value
|
45
|
+
when true
|
46
|
+
true
|
47
|
+
when false, nil, ActiveModel::Type::Boolean::FALSE_VALUES
|
48
|
+
false
|
49
|
+
else
|
50
|
+
if value.respond_to?(:to_i) && ( Numeric === value || value.to_s !~ /[^0-9]/ )
|
51
|
+
!value.to_i.zero?
|
52
|
+
elsif value.respond_to?(:zero?)
|
53
|
+
!value.zero?
|
54
|
+
else
|
55
|
+
!value.blank?
|
56
|
+
end
|
57
|
+
end
|
32
58
|
end
|
33
59
|
|
34
60
|
class_methods do
|
61
|
+
# Access or set class-wide json_attribute_config. Inherited by sub-classes,
|
62
|
+
# but setting on sub-classes is unique to subclass. Similar to how
|
63
|
+
# rails class_attribute's are used.
|
64
|
+
#
|
65
|
+
# @example access config
|
66
|
+
# SomeClass.attr_json_config
|
67
|
+
#
|
68
|
+
# @example set config variables
|
69
|
+
# class SomeClass < ActiveRecordBase
|
70
|
+
# include JsonAttribute::Record
|
71
|
+
#
|
72
|
+
# attr_json_config(default_container_attribute: "some_column")
|
73
|
+
# end
|
74
|
+
# TODO make Model match please.
|
75
|
+
def attr_json_config(new_values = {})
|
76
|
+
if new_values.present?
|
77
|
+
# get one without new values, then merge new values into it, and
|
78
|
+
# set it locally for this class.
|
79
|
+
@attr_json_config = attr_json_config.merge(new_values)
|
80
|
+
else
|
81
|
+
if instance_variable_defined?("@attr_json_config")
|
82
|
+
# we have a custom one for this class, return it.
|
83
|
+
@attr_json_config
|
84
|
+
elsif superclass.respond_to?(:attr_json_config)
|
85
|
+
# return superclass without setting it locally, so changes in superclass
|
86
|
+
# will continue effecting us.
|
87
|
+
superclass.attr_json_config
|
88
|
+
else
|
89
|
+
# no superclass, no nothing, set it to blank one.
|
90
|
+
@attr_json_config = Config.new(mode: :record)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
|
35
97
|
# Type can be a symbol that will be looked up in `ActiveModel::Type.lookup`,
|
36
98
|
# or an ActiveModel:::Type::Value).
|
37
99
|
#
|
@@ -47,9 +109,9 @@ module AttrJson
|
|
47
109
|
# @option options [String,Symbol] :store_key (nil) Serialize to JSON using
|
48
110
|
# given store_key, rather than name as would be usual.
|
49
111
|
#
|
50
|
-
# @option options [Symbol,String] :container_attribute (
|
112
|
+
# @option options [Symbol,String] :container_attribute (attr_json_config.default_container_attribute, normally `json_attributes`) The real
|
51
113
|
# json(b) ActiveRecord attribute/column to serialize as a key in. Defaults to
|
52
|
-
# `
|
114
|
+
# `attr_json_config.default_container_attribute`, which defaults to `:json_attributes`
|
53
115
|
#
|
54
116
|
# @option options [Boolean] :validate (true) Create an ActiveRecord::Validations::AssociatedValidator so
|
55
117
|
# validation errors on the attributes post up to self.
|
@@ -57,14 +119,16 @@ module AttrJson
|
|
57
119
|
# @option options [Boolean] :rails_attribute (false) Create an actual ActiveRecord
|
58
120
|
# `attribute` for name param. A Rails attribute isn't needed for our functionality,
|
59
121
|
# but registering thusly will let the type be picked up by simple_form and
|
60
|
-
# other tools that may look for it via Rails attribute APIs.
|
122
|
+
# other tools that may look for it via Rails attribute APIs. Default can be changed
|
123
|
+
# with `attr_json_config(default_rails_attribute: true)`
|
61
124
|
def attr_json(name, type, **options)
|
62
125
|
options = {
|
63
|
-
rails_attribute:
|
126
|
+
rails_attribute: self.attr_json_config.default_rails_attribute,
|
64
127
|
validate: true,
|
65
|
-
container_attribute: self.
|
128
|
+
container_attribute: self.attr_json_config.default_container_attribute,
|
129
|
+
accepts_nested_attributes: self.attr_json_config.default_accepts_nested_attributes
|
66
130
|
}.merge!(options)
|
67
|
-
options.assert_valid_keys(AttributeDefinition::VALID_OPTIONS + [:validate, :rails_attribute])
|
131
|
+
options.assert_valid_keys(AttributeDefinition::VALID_OPTIONS + [:validate, :rails_attribute, :accepts_nested_attributes])
|
68
132
|
container_attribute = options[:container_attribute]
|
69
133
|
|
70
134
|
# TODO arg check container_attribute make sure it exists. Hard cause
|
@@ -74,13 +138,19 @@ module AttrJson
|
|
74
138
|
# only if it hasn't already been done. WARNING we are using internal
|
75
139
|
# Rails API here, but only way to do this lazily, which I thought was
|
76
140
|
# worth it. On the other hand, I think .attribute is idempotent, maybe we don't need it...
|
141
|
+
#
|
142
|
+
# We set default to empty hash, because that 'tricks' AR into knowing any
|
143
|
+
# application of defaults is a change that needs to be saved.
|
77
144
|
unless attributes_to_define_after_schema_loads[container_attribute.to_s] &&
|
78
|
-
attributes_to_define_after_schema_loads[container_attribute.to_s].first.is_a?(AttrJson::Type::ContainerAttribute)
|
79
|
-
|
145
|
+
attributes_to_define_after_schema_loads[container_attribute.to_s].first.is_a?(AttrJson::Type::ContainerAttribute) &&
|
146
|
+
attributes_to_define_after_schema_loads[container_attribute.to_s].first.model == self
|
147
|
+
# If this is already defined, but was for superclass, we need to define it again for
|
148
|
+
# this class.
|
149
|
+
attribute container_attribute.to_sym, AttrJson::Type::ContainerAttribute.new(self, container_attribute), default: -> { {} }
|
80
150
|
end
|
81
151
|
|
82
152
|
self.attr_json_registry = attr_json_registry.with(
|
83
|
-
AttributeDefinition.new(name.to_sym, type, options.except(:rails_attribute, :validate))
|
153
|
+
AttributeDefinition.new(name.to_sym, type, options.except(:rails_attribute, :validate, :accepts_nested_attributes))
|
84
154
|
)
|
85
155
|
|
86
156
|
# By default, automatically validate nested models
|
@@ -91,36 +161,54 @@ module AttrJson
|
|
91
161
|
# We don't actually use this for anything, we provide our own covers. But registering
|
92
162
|
# it with usual system will let simple_form and maybe others find it.
|
93
163
|
if options[:rails_attribute]
|
94
|
-
|
164
|
+
attr_json_definition = attr_json_registry[name]
|
165
|
+
|
166
|
+
attribute_args = attr_json_definition.has_default? ? { default: attr_json_definition.default_argument } : {}
|
167
|
+
self.attribute name.to_sym, attr_json_definition.type, **attribute_args
|
168
|
+
|
169
|
+
# Ensure that rails attributes tracker knows about value we just fetched
|
170
|
+
# for this particular attribute. Yes, we are registering an after_find for each
|
171
|
+
# attr_json registered with rails_attribute:true, using the `name` from above under closure. .
|
172
|
+
after_find do
|
173
|
+
value = public_send(name)
|
174
|
+
if value && has_attribute?(name.to_sym)
|
175
|
+
write_attribute(name.to_sym, value)
|
176
|
+
self.send(:clear_attribute_changes, [name.to_sym])
|
177
|
+
end
|
178
|
+
end
|
95
179
|
end
|
96
180
|
|
97
181
|
_attr_jsons_module.module_eval do
|
182
|
+
# For getter and setter, we used to use read_store_attribute/write_store_attribute
|
183
|
+
# copied from Rails store_accessor implementation.
|
184
|
+
# https://github.com/rails/rails/blob/74c3e43fba458b9b863d27f0c45fd2d8dc603cbc/activerecord/lib/active_record/store.rb#L90-L96
|
185
|
+
#
|
186
|
+
# But in fact just getting/setting in the hash provided to us by ActiveRecord json type
|
187
|
+
# container works BETTER for dirty tracking. We had a test that only passed doing it
|
188
|
+
# this simple way.
|
189
|
+
|
98
190
|
define_method("#{name}=") do |value|
|
191
|
+
super(value) if defined?(super)
|
99
192
|
attribute_def = self.class.attr_json_registry.fetch(name.to_sym)
|
100
|
-
|
101
|
-
# https://github.com/rails/rails/blob/74c3e43fba458b9b863d27f0c45fd2d8dc603cbc/activerecord/lib/active_record/store.rb#L90-L96
|
102
|
-
|
103
|
-
# special handling for nil, sorry, because if name key was previously
|
104
|
-
# not present, write_store_attribute by default will decide there was
|
105
|
-
# no change and refuse to make the change. TODO messy.
|
106
|
-
if value.nil? && !public_send(attribute_def.container_attribute).has_key?(attribute_def.store_key)
|
107
|
-
public_send :"#{attribute_def.container_attribute}_will_change!"
|
108
|
-
public_send(attribute_def.container_attribute)[attribute_def.store_key] = nil
|
109
|
-
else
|
110
|
-
# use of `write_store_attribute` is copied from Rails store_accessor implementation.
|
111
|
-
# https://github.com/rails/rails/blob/74c3e43fba458b9b863d27f0c45fd2d8dc603cbc/activerecord/lib/active_record/store.rb#L90-L96
|
112
|
-
write_store_attribute(attribute_def.container_attribute, attribute_def.store_key, attribute_def.cast(value))
|
113
|
-
end
|
193
|
+
public_send(attribute_def.container_attribute)[attribute_def.store_key] = attribute_def.cast(value)
|
114
194
|
end
|
115
195
|
|
116
196
|
define_method("#{name}") do
|
117
197
|
attribute_def = self.class.attr_json_registry.fetch(name.to_sym)
|
198
|
+
public_send(attribute_def.container_attribute)[attribute_def.store_key]
|
199
|
+
end
|
118
200
|
|
119
|
-
|
120
|
-
#
|
121
|
-
|
201
|
+
define_method("#{name}?") do
|
202
|
+
# implementation of `query_store_attribute` is based on Rails `query_attribute` implementation
|
203
|
+
AttrJson::Record.attr_json_query_method(self, name)
|
122
204
|
end
|
123
205
|
end
|
206
|
+
|
207
|
+
# Default attr_json_accepts_nested_attributes_for values
|
208
|
+
if options[:accepts_nested_attributes]
|
209
|
+
options = options[:accepts_nested_attributes] == true ? {} : options[:accepts_nested_attributes]
|
210
|
+
self.attr_json_accepts_nested_attributes_for name, **options
|
211
|
+
end
|
124
212
|
end
|
125
213
|
|
126
214
|
private
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module AttrJson
|
2
|
+
|
3
|
+
# A little wrapper to provide an object that provides #dump and #load method for use
|
4
|
+
# as a coder second-argument for [ActiveRecord Serialization](https://api.rubyonrails.org/classes/ActiveRecord/AttributeMethods/Serialization/ClassMethods.html),
|
5
|
+
# that simply delegates to #serialize and #deserialize from a ActiveModel::Type object.
|
6
|
+
#
|
7
|
+
# Created to be used with an AttrJson::Model type (AttrJson::Type::Model), but hypothetically
|
8
|
+
# could be a shim from anything with serialize/deserialize to dump/load instead.
|
9
|
+
#
|
10
|
+
# class ValueModel
|
11
|
+
# include AttrJson::Model
|
12
|
+
# attr_json :some_string, :string
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# class SomeModel < ApplicationRecord
|
16
|
+
# serialize :some_json_column, ValueModel.to_serialize_coder
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# Note when used with an AttrJson::Model, it will dump/load from a HASH, not a
|
20
|
+
# string. It assumes it's writing to a Json(b) column that wants/provides hashes,
|
21
|
+
# not strings.
|
22
|
+
class SerializationCoderFromType
|
23
|
+
attr_reader :type
|
24
|
+
def initialize(type)
|
25
|
+
@type = type
|
26
|
+
end
|
27
|
+
|
28
|
+
# Dump and load methods to support ActiveRecord Serialization
|
29
|
+
# too.
|
30
|
+
def dump(value)
|
31
|
+
type.serialize(value)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Dump and load methods to support ActiveRecord Serialization
|
35
|
+
# too. https://api.rubyonrails.org/classes/ActiveRecord/AttributeMethods/Serialization/ClassMethods.html
|
36
|
+
def load(value)
|
37
|
+
type.deserialize(value)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/attr_json/type/array.rb
CHANGED
@@ -41,6 +41,12 @@ module AttrJson
|
|
41
41
|
]
|
42
42
|
end
|
43
43
|
|
44
|
+
# Hacky, hard-coded classes, but used in our weird primitive implementation in NestedAttributes,
|
45
|
+
# better than putting the conditionals there
|
46
|
+
def base_type_primitive?
|
47
|
+
!(base_type.is_a?(AttrJson::Type::Model) || base_type.is_a?(AttrJson::Type::PolymorphicModel))
|
48
|
+
end
|
49
|
+
|
44
50
|
protected
|
45
51
|
def convert_to_array(value)
|
46
52
|
if value.kind_of?(Hash)
|
@@ -38,19 +38,30 @@ module AttrJson
|
|
38
38
|
[key, attr_def ? attr_def.serialize(value) : value]
|
39
39
|
end.to_h)
|
40
40
|
end
|
41
|
-
|
42
|
-
|
41
|
+
|
42
|
+
# optional with_defaults arg is our own, not part of ActiveModel::Type API,
|
43
|
+
# used by {#changed_in_place?} so we can consider default application to
|
44
|
+
# be a change.
|
45
|
+
def deserialize(v, with_defaults: true)
|
46
|
+
h = super(v) || {}
|
43
47
|
model.attr_json_registry.definitions.each do |attr_def|
|
44
48
|
next unless container_attribute.to_s == attr_def.container_attribute.to_s
|
45
49
|
|
46
50
|
if h.has_key?(attr_def.store_key)
|
47
51
|
h[attr_def.store_key] = attr_def.deserialize(h[attr_def.store_key])
|
48
|
-
elsif attr_def.has_default?
|
52
|
+
elsif with_defaults && attr_def.has_default?
|
49
53
|
h[attr_def.store_key] = attr_def.provide_default!
|
50
54
|
end
|
51
55
|
end
|
52
56
|
h
|
53
57
|
end
|
58
|
+
|
59
|
+
# Just like superclass, but we tell deserialize to NOT apply defaults,
|
60
|
+
# so we can consider default-application to be a change.
|
61
|
+
def changed_in_place?(raw_old_value, new_value)
|
62
|
+
deserialize(raw_old_value, with_defaults: false) != new_value
|
63
|
+
end
|
64
|
+
|
54
65
|
end
|
55
66
|
end
|
56
67
|
end
|
data/lib/attr_json/type/model.rb
CHANGED
@@ -7,7 +7,10 @@ module AttrJson
|
|
7
7
|
# You create one with AttrJson::Model::Type.new(attr_json_model_class),
|
8
8
|
# but normally that's only done in AttrJson::Model.to_type, there isn't
|
9
9
|
# an anticipated need to create from any other place.
|
10
|
+
#
|
10
11
|
class Model < ::ActiveModel::Type::Value
|
12
|
+
class BadCast < ArgumentError ; end
|
13
|
+
|
11
14
|
attr_accessor :model
|
12
15
|
def initialize(model)
|
13
16
|
#TODO type check, it really better be a AttrJson::Model. maybe?
|
@@ -29,15 +32,18 @@ module AttrJson
|
|
29
32
|
# to_hash is actually the 'implicit' conversion, it really is a hash
|
30
33
|
# even though it isn't is_a?(Hash), try to_hash first before to_h,
|
31
34
|
# the explicit conversion.
|
32
|
-
model.
|
35
|
+
model.new(v.to_hash)
|
33
36
|
elsif v.respond_to?(:to_h)
|
34
37
|
# TODO Maybe we ought not to do this on #to_h?
|
35
|
-
model.
|
36
|
-
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
38
|
+
model.new(v.to_h)
|
39
|
+
elsif model.attr_json_config.bad_cast == :as_nil
|
40
|
+
# This was originally default behavior, to be like existing ActiveRecord
|
41
|
+
# which kind of silently does this for non-castable basic values. That
|
42
|
+
# ended up being confusing in the basic case, so now we raise by default,
|
43
|
+
# but this is still configurable.
|
40
44
|
nil
|
45
|
+
else
|
46
|
+
raise BadCast.new("Can not cast from #{v.inspect} to #{self.type}")
|
41
47
|
end
|
42
48
|
end
|
43
49
|
|
@@ -47,12 +53,36 @@ module AttrJson
|
|
47
53
|
elsif v.kind_of?(model)
|
48
54
|
v.serializable_hash
|
49
55
|
else
|
50
|
-
cast(v).serializable_hash
|
56
|
+
(cast_v = cast(v)) && cast_v.serializable_hash
|
51
57
|
end
|
52
58
|
end
|
53
59
|
|
54
60
|
def deserialize(v)
|
55
|
-
|
61
|
+
if v.nil?
|
62
|
+
# important to stay nil instead of empty object, because they
|
63
|
+
# are different things.
|
64
|
+
v
|
65
|
+
elsif v.kind_of? model
|
66
|
+
v
|
67
|
+
elsif v.respond_to?(:to_hash)
|
68
|
+
# to_hash is actually the 'implicit' conversion, it really is a hash
|
69
|
+
# even though it isn't is_a?(Hash), try to_hash first before to_h,
|
70
|
+
# the explicit conversion.
|
71
|
+
model.new_from_serializable(v.to_hash)
|
72
|
+
elsif v.respond_to?(:to_h)
|
73
|
+
# TODO Maybe we ought not to do this on #to_h? especially here in deserialize?
|
74
|
+
model.new_from_serializable(v.to_h)
|
75
|
+
elsif model.attr_json_config.bad_cast == :as_nil
|
76
|
+
# TODO should we have different config value for bad_deserialize vs bad_cast?
|
77
|
+
|
78
|
+
# This was originally default behavior, to be like existing ActiveRecord
|
79
|
+
# which kind of silently does this for non-castable basic values. That
|
80
|
+
# ended up being confusing in the basic case, so now we raise by default,
|
81
|
+
# but this is still configurable.
|
82
|
+
nil
|
83
|
+
else
|
84
|
+
raise BadCast.new("Can not cast from #{v.inspect} to #{self.type}")
|
85
|
+
end
|
56
86
|
end
|
57
87
|
|
58
88
|
# these guys are definitely mutable, so we need this.
|
@@ -51,6 +51,8 @@ module AttrJson
|
|
51
51
|
# MyRecord.jsonb_contains(author: { name: "foo", type: "Corporation"})
|
52
52
|
# MyRecord.jsonb_contains(author: Corporation.new(name: "foo"))
|
53
53
|
#
|
54
|
+
# Additionally, there is not_jsonb_contains, which creates the same query terms like jsonb_contains, but negated.
|
55
|
+
#
|
54
56
|
class PolymorphicModel < ActiveModel::Type::Value
|
55
57
|
class TypeError < ::TypeError ; end
|
56
58
|
|
@@ -112,6 +114,11 @@ module AttrJson
|
|
112
114
|
end
|
113
115
|
|
114
116
|
def serialize(v)
|
117
|
+
return nil if v.nil?
|
118
|
+
|
119
|
+
# if it's not already a model cast it to a model if possible (eg it's a hash)
|
120
|
+
v = cast(v)
|
121
|
+
|
115
122
|
model_name = v.class.name
|
116
123
|
type = type_for_model_name(model_name)
|
117
124
|
|
data/lib/attr_json/version.rb
CHANGED
data/lib/attr_json.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: attr_json
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonathan Rochkind
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-01-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -19,7 +19,7 @@ dependencies:
|
|
19
19
|
version: 5.0.0
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: '
|
22
|
+
version: '7.1'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -29,21 +29,21 @@ dependencies:
|
|
29
29
|
version: 5.0.0
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: '
|
32
|
+
version: '7.1'
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: bundler
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
36
36
|
requirements:
|
37
|
-
- - "
|
37
|
+
- - ">="
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version: '
|
39
|
+
version: '0'
|
40
40
|
type: :development
|
41
41
|
prerelease: false
|
42
42
|
version_requirements: !ruby/object:Gem::Requirement
|
43
43
|
requirements:
|
44
|
-
- - "
|
44
|
+
- - ">="
|
45
45
|
- !ruby/object:Gem::Version
|
46
|
-
version: '
|
46
|
+
version: '0'
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: rake
|
49
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -64,30 +64,44 @@ dependencies:
|
|
64
64
|
requirements:
|
65
65
|
- - "~>"
|
66
66
|
- !ruby/object:Gem::Version
|
67
|
-
version: '3.
|
67
|
+
version: '3.7'
|
68
68
|
type: :development
|
69
69
|
prerelease: false
|
70
70
|
version_requirements: !ruby/object:Gem::Requirement
|
71
71
|
requirements:
|
72
72
|
- - "~>"
|
73
73
|
- !ruby/object:Gem::Version
|
74
|
-
version: '3.
|
74
|
+
version: '3.7'
|
75
75
|
- !ruby/object:Gem::Dependency
|
76
|
-
name:
|
76
|
+
name: yard-activesupport-concern
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: appraisal
|
77
91
|
requirement: !ruby/object:Gem::Requirement
|
78
92
|
requirements:
|
79
93
|
- - "~>"
|
80
94
|
- !ruby/object:Gem::Version
|
81
|
-
version: '
|
95
|
+
version: '2.2'
|
82
96
|
type: :development
|
83
97
|
prerelease: false
|
84
98
|
version_requirements: !ruby/object:Gem::Requirement
|
85
99
|
requirements:
|
86
100
|
- - "~>"
|
87
101
|
- !ruby/object:Gem::Version
|
88
|
-
version: '
|
102
|
+
version: '2.2'
|
89
103
|
- !ruby/object:Gem::Dependency
|
90
|
-
name:
|
104
|
+
name: rexml
|
91
105
|
requirement: !ruby/object:Gem::Requirement
|
92
106
|
requirements:
|
93
107
|
- - ">="
|
@@ -100,6 +114,20 @@ dependencies:
|
|
100
114
|
- - ">="
|
101
115
|
- !ruby/object:Gem::Version
|
102
116
|
version: '0'
|
117
|
+
- !ruby/object:Gem::Dependency
|
118
|
+
name: webrick
|
119
|
+
requirement: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - "~>"
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '1.0'
|
124
|
+
type: :development
|
125
|
+
prerelease: false
|
126
|
+
version_requirements: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - "~>"
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: '1.0'
|
103
131
|
description: |-
|
104
132
|
ActiveRecord attributes stored serialized in a json column, super smooth.
|
105
133
|
For Rails 5.0, 5.1, or 5.2. Typed and cast like Active Record. Supporting nested models,
|
@@ -114,10 +142,13 @@ executables: []
|
|
114
142
|
extensions: []
|
115
143
|
extra_rdoc_files: []
|
116
144
|
files:
|
145
|
+
- ".github/workflows/ci.yml"
|
146
|
+
- ".github/workflows/future_rails_ci.yml"
|
117
147
|
- ".gitignore"
|
118
148
|
- ".rspec"
|
119
|
-
- ".travis.yml"
|
120
149
|
- ".yardopts"
|
150
|
+
- Appraisals
|
151
|
+
- CHANGELOG.md
|
121
152
|
- Gemfile
|
122
153
|
- LICENSE.txt
|
123
154
|
- README.md
|
@@ -130,9 +161,18 @@ files:
|
|
130
161
|
- config.ru
|
131
162
|
- doc_src/dirty_tracking.md
|
132
163
|
- doc_src/forms.md
|
164
|
+
- gemfiles/.bundle/config
|
165
|
+
- gemfiles/rails_5_0.gemfile
|
166
|
+
- gemfiles/rails_5_1.gemfile
|
167
|
+
- gemfiles/rails_5_2.gemfile
|
168
|
+
- gemfiles/rails_6_0.gemfile
|
169
|
+
- gemfiles/rails_6_1.gemfile
|
170
|
+
- gemfiles/rails_7_0.gemfile
|
171
|
+
- gemfiles/rails_edge.gemfile
|
133
172
|
- lib/attr_json.rb
|
134
173
|
- lib/attr_json/attribute_definition.rb
|
135
174
|
- lib/attr_json/attribute_definition/registry.rb
|
175
|
+
- lib/attr_json/config.rb
|
136
176
|
- lib/attr_json/model.rb
|
137
177
|
- lib/attr_json/model/cocoon_compat.rb
|
138
178
|
- lib/attr_json/nested_attributes.rb
|
@@ -143,6 +183,7 @@ files:
|
|
143
183
|
- lib/attr_json/record/dirty.rb
|
144
184
|
- lib/attr_json/record/query_builder.rb
|
145
185
|
- lib/attr_json/record/query_scopes.rb
|
186
|
+
- lib/attr_json/serialization_coder_from_type.rb
|
146
187
|
- lib/attr_json/type/array.rb
|
147
188
|
- lib/attr_json/type/container_attribute.rb
|
148
189
|
- lib/attr_json/type/model.rb
|
@@ -155,7 +196,7 @@ licenses:
|
|
155
196
|
metadata:
|
156
197
|
homepage_uri: https://github.com/jrochkind/attr_json
|
157
198
|
source_code_uri: https://github.com/jrochkind/attr_json
|
158
|
-
post_install_message:
|
199
|
+
post_install_message:
|
159
200
|
rdoc_options: []
|
160
201
|
require_paths:
|
161
202
|
- lib
|
@@ -163,16 +204,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
163
204
|
requirements:
|
164
205
|
- - ">="
|
165
206
|
- !ruby/object:Gem::Version
|
166
|
-
version:
|
207
|
+
version: 2.4.0
|
167
208
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
168
209
|
requirements:
|
169
210
|
- - ">="
|
170
211
|
- !ruby/object:Gem::Version
|
171
212
|
version: '0'
|
172
213
|
requirements: []
|
173
|
-
|
174
|
-
|
175
|
-
signing_key:
|
214
|
+
rubygems_version: 3.2.33
|
215
|
+
signing_key:
|
176
216
|
specification_version: 4
|
177
217
|
summary: ActiveRecord attributes stored serialized in a json column, super smooth.
|
178
218
|
test_files: []
|
data/.travis.yml
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
#
|
2
|
-
dist: trusty
|
3
|
-
sudo: false
|
4
|
-
addons:
|
5
|
-
postgresql: '9.4'
|
6
|
-
chrome: stable
|
7
|
-
language: ruby
|
8
|
-
cache: bundler
|
9
|
-
rvm:
|
10
|
-
- 2.4
|
11
|
-
- 2.5.0
|
12
|
-
env:
|
13
|
-
- RAILS_GEM="~> 5.0.0" PG_GEM="~> 0.18"
|
14
|
-
- RAILS_GEM="~> 5.1.0"
|
15
|
-
- RAILS_GEM=">= 5.2.0.rc2,< 5.3.0"
|
16
|
-
before_install:
|
17
|
-
- gem install bundler -v 1.14.6
|