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.
@@ -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 < ActiveRecord::Base
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
- class_attribute :default_json_container_attribute, instance_acessor: false
31
- self.default_json_container_attribute ||= DEFAULT_CONTAINER_ATTRIBUTE
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 (self.default_json_container_attribute) The real
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
- # `self.default_json_container_attribute`, which defaults to `:attr_jsons`
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: false,
126
+ rails_attribute: self.attr_json_config.default_rails_attribute,
64
127
  validate: true,
65
- container_attribute: self.default_json_container_attribute
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
- attribute container_attribute.to_sym, AttrJson::Type::ContainerAttribute.new(self, container_attribute)
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
- self.attribute name.to_sym, self.attr_json_registry.fetch(name).type
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
- # write_store_attribute copied from Rails store_accessor implementation.
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
- # use of `read_store_attribute` is copied from Rails store_accessor implementation.
120
- # https://github.com/rails/rails/blob/74c3e43fba458b9b863d27f0c45fd2d8dc603cbc/activerecord/lib/active_record/store.rb#L90-L96
121
- read_store_attribute(attribute_def.container_attribute, attribute_def.store_key)
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
@@ -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
- def deserialize(v)
42
- h = super || {}
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
@@ -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.new_from_serializable(v.to_hash)
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.new_from_serializable(v.to_h)
36
- else
37
- # Bad input? Most existing ActiveModel::Types seem to decide
38
- # either nil, or a base value like the empty string. They don't
39
- # raise. So we won't either, just nil.
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
- cast(v)
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
 
@@ -1,3 +1,3 @@
1
1
  module AttrJson
2
- VERSION = "0.2.0"
2
+ VERSION = "1.5.0"
3
3
  end
data/lib/attr_json.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  require "attr_json/version"
2
2
 
3
3
  require "active_record"
4
- require "active_record/connection_adapters/postgresql_adapter"
5
4
 
5
+ require 'attr_json/config'
6
6
  require 'attr_json/record'
7
7
  require 'attr_json/model'
8
8
  require 'attr_json/nested_attributes'
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: 0.2.0
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: 2018-05-04 00:00:00.000000000 Z
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: '5.3'
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: '5.3'
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: '1.14'
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: '1.14'
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.5'
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.5'
74
+ version: '3.7'
75
75
  - !ruby/object:Gem::Dependency
76
- name: database_cleaner
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: '1.5'
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: '1.5'
102
+ version: '2.2'
89
103
  - !ruby/object:Gem::Dependency
90
- name: yard-activesupport-concern
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: '0'
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
- rubyforge_project:
174
- rubygems_version: 2.6.13
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