attr_json 0.7.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.
@@ -2,16 +2,17 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "combustion", git: "https://github.com/pat/combustion.git"
6
- gem "rails", ">= 6.0.0.beta1", "< 6.1"
7
- gem "railties"
5
+ gem "combustion", "~> 1.0"
6
+ gem "rails", ">= 6.0.0", "< 6.1"
8
7
  gem "pg", "~> 1.0"
9
- gem "rspec-rails", "~> 3.7"
8
+ gem "rspec-rails", "~> 4.0"
10
9
  gem "simple_form", ">= 4.0"
11
10
  gem "cocoon", ">= 1.2"
12
11
  gem "jquery-rails"
12
+ gem "coffee-rails"
13
+ gem "sprockets-rails"
13
14
  gem "capybara", "~> 3.0"
14
- gem "webdrivers", "~> 3.0"
15
+ gem "webdrivers", "~> 4.0"
15
16
  gem "selenium-webdriver"
16
17
  gem "byebug"
17
18
 
@@ -0,0 +1,19 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "combustion", "~> 1.0"
6
+ gem "rails", "~> 6.1.0"
7
+ gem "pg", "~> 1.0"
8
+ gem "rspec-rails", "~> 4.0"
9
+ gem "simple_form", ">= 4.0"
10
+ gem "cocoon", ">= 1.2"
11
+ gem "jquery-rails"
12
+ gem "coffee-rails"
13
+ gem "sprockets-rails"
14
+ gem "capybara", "~> 3.0"
15
+ gem "webdrivers", "~> 4.0"
16
+ gem "selenium-webdriver"
17
+ gem "byebug"
18
+
19
+ gemspec path: "../"
@@ -0,0 +1,19 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "combustion", "~> 1.0"
6
+ gem "rails", "~> 7.0.0"
7
+ gem "pg", "~> 1.0"
8
+ gem "rspec-rails", "~> 4.0"
9
+ gem "simple_form", ">= 4.0"
10
+ gem "cocoon", ">= 1.2"
11
+ gem "jquery-rails"
12
+ gem "coffee-rails"
13
+ gem "sprockets-rails"
14
+ gem "capybara", "~> 3.0"
15
+ gem "webdrivers", "~> 4.0"
16
+ gem "selenium-webdriver"
17
+ gem "byebug"
18
+
19
+ gemspec path: "../"
@@ -2,18 +2,18 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "combustion", git: "https://github.com/pat/combustion.git"
6
- gem "rails", git: "https://github.com/rails/rails.git", branch: "master"
7
- gem "railties"
5
+ gem "combustion", "~> 1.0", github: "pat/combustion"
6
+ gem "rails", git: "https://github.com/rails/rails.git", branch: "main"
8
7
  gem "pg", "~> 1.0"
9
- gem "rspec-rails", "~> 3.7"
8
+ gem "rspec-rails", "~> 4.0"
10
9
  gem "simple_form", ">= 4.0"
11
10
  gem "cocoon", ">= 1.2"
12
11
  gem "jquery-rails"
12
+ gem "coffee-rails"
13
+ gem "sprockets-rails"
13
14
  gem "capybara", "~> 3.0"
14
- gem "webdrivers", "~> 3.0"
15
+ gem "webdrivers", "~> 4.0"
15
16
  gem "selenium-webdriver"
16
17
  gem "byebug"
17
- gem "coffee-rails"
18
18
 
19
19
  gemspec path: "../"
@@ -78,6 +78,12 @@
78
78
  @default != NO_DEFAULT_PROVIDED
79
79
  end
80
80
 
81
+ # Can be value or proc!
82
+ def default_argument
83
+ return nil unless has_default?
84
+ @default
85
+ end
86
+
81
87
  def provide_default!
82
88
  unless has_default?
83
89
  raise ArgumentError.new("This #{self.class.name} does not have a default defined!")
@@ -3,10 +3,20 @@ module AttrJson
3
3
  # and rails class_attribute. Instead, you set to new Config object
4
4
  # changed with {#merge}.
5
5
  class Config
6
- RECORD_ALLOWED_KEYS = %i{default_container_attribute default_accepts_nested_attributes}
7
- MODEL_ALLOWED_KEYS = %i{unknown_key}
6
+ RECORD_ALLOWED_KEYS = %i{
7
+ default_container_attribute
8
+ default_rails_attribute
9
+ default_accepts_nested_attributes
10
+ }
11
+
12
+ MODEL_ALLOWED_KEYS = %i{
13
+ unknown_key
14
+ bad_cast
15
+ }
16
+
8
17
  DEFAULTS = {
9
18
  default_container_attribute: "json_attributes",
19
+ default_rails_attribute: false,
10
20
  unknown_key: :raise
11
21
  }
12
22
 
@@ -7,6 +7,8 @@ require 'attr_json/attribute_definition/registry'
7
7
  require 'attr_json/type/model'
8
8
  require 'attr_json/model/cocoon_compat'
9
9
 
10
+ require 'attr_json/serialization_coder_from_type'
11
+
10
12
  module AttrJson
11
13
 
12
14
  # Meant for use in a plain class, turns it into an ActiveModel::Model
@@ -30,9 +32,39 @@ module AttrJson
30
32
  #
31
33
  # class Something
32
34
  # include AttrJson::Model
33
- # attr_json_config(unknown_key: :ignore)
35
+ # attr_json_config(unknown_key: :allow)
36
+ # #...
37
+ # end
38
+ #
39
+ # Similarly, trying to set a Model-valued attribute with an object that
40
+ # can't be cast to a Hash or Model at all will normally raise a
41
+ # AttrJson::Type::Model::BadCast error, but you can set config `bad_cast: :as_nil`
42
+ # to make it cast to nil, more like typical ActiveRecord cast.
43
+ #
44
+ # class Something
45
+ # include AttrJson::Model
46
+ # attr_json_config(bad_cast: :as_nil)
34
47
  # #...
35
48
  # end
49
+ #
50
+ # ## ActiveRecord `serialize`
51
+ #
52
+ # If you want to map a single AttrJson::Model to a json/jsonb column, you
53
+ # can use ActiveRecord `serialize` feature.
54
+ #
55
+ # https://api.rubyonrails.org/classes/ActiveRecord/AttributeMethods/Serialization/ClassMethods.html
56
+ #
57
+ # We provide a simple shim to give you the right API for a "coder" for AR serialize:
58
+ #
59
+ # class ValueModel
60
+ # include AttrJson::Model
61
+ # attr_json :some_string, :string
62
+ # end
63
+ #
64
+ # class SomeModel < ApplicationRecord
65
+ # serialize :some_json_column, ValueModel.to_serialize_coder
66
+ # end
67
+ #
36
68
  module Model
37
69
  extend ActiveSupport::Concern
38
70
 
@@ -71,16 +103,27 @@ module AttrJson
71
103
  end
72
104
 
73
105
 
74
- # Like `.new`, but translate store keys in hash
106
+ # The inverse of model#serializable_hash -- re-hydrates a serialized hash to a model.
107
+ #
108
+ # Similar to `.new`, but translates things that need to be translated in deserialization,
109
+ # like store_keys, and properly calling deserialize on the underlying types.
110
+ #
111
+ # @example Model.new_from_serializable(hash)
75
112
  def new_from_serializable(attributes = {})
76
- attributes = attributes.transform_keys do |key|
113
+ attributes = attributes.collect do |key, value|
77
114
  # store keys in arguments get translated to attribute names on initialize.
78
115
  if attribute_def = self.attr_json_registry.store_key_lookup("", key.to_s)
79
- attribute_def.name.to_s
80
- else
81
- key
116
+ key = attribute_def.name.to_s
82
117
  end
83
- end
118
+
119
+ attr_type = self.attr_json_registry.has_attribute?(key) && self.attr_json_registry.type_for_attribute(key)
120
+ if attr_type
121
+ value = attr_type.deserialize(value)
122
+ end
123
+
124
+ [key, value]
125
+ end.to_h
126
+
84
127
  self.new(attributes)
85
128
  end
86
129
 
@@ -88,6 +131,21 @@ module AttrJson
88
131
  @type ||= AttrJson::Type::Model.new(self)
89
132
  end
90
133
 
134
+ def to_serialization_coder
135
+ @serialization_coder ||= AttrJson::SerializationCoderFromType.new(to_type)
136
+ end
137
+
138
+ # like the ActiveModel::Attributes method
139
+ def attribute_names
140
+ attr_json_registry.attribute_names
141
+ end
142
+
143
+ # like the ActiveModel::Attributes method, hash with name keys, and ActiveModel::Type values
144
+ def attribute_types
145
+ attribute_names.collect { |name| [name.to_s, attr_json_registry.type_for_attribute(name)]}.to_h
146
+ end
147
+
148
+
91
149
  # Type can be an instance of an ActiveModel::Type::Value subclass, or a symbol that will
92
150
  # be looked up in `ActiveModel::Type.lookup`
93
151
  #
@@ -130,27 +188,6 @@ module AttrJson
130
188
  end
131
189
  end
132
190
 
133
- # This should kind of be considered 'protected', but the semantics
134
- # of how we want to call it don't give us a visibility modifier that works.
135
- # Prob means refactoring called for. TODO?
136
- def fill_in_defaults(hash)
137
- # Only if we need to mutate it to add defaults, we'll dup it first. deep_dup not neccesary
138
- # since we're only modifying top-level here.
139
- duped = false
140
- attr_json_registry.definitions.each do |definition|
141
- if definition.has_default? && ! (hash.has_key?(definition.store_key.to_s) || hash.has_key?(definition.store_key.to_sym))
142
- unless duped
143
- hash = hash.dup
144
- duped = true
145
- end
146
-
147
- hash[definition.store_key] = definition.provide_default!
148
- end
149
- end
150
-
151
- hash
152
- end
153
-
154
191
  private
155
192
 
156
193
  # Define an anonymous module and include it, so can still be easily
@@ -166,11 +203,15 @@ module AttrJson
166
203
  end
167
204
 
168
205
  def initialize(attributes = {})
169
- if !attributes.respond_to?(:transform_keys)
170
- raise ArgumentError, "When assigning attributes, you must pass a hash as an argument."
171
- end
206
+ super
207
+
208
+ fill_in_defaults!
209
+ end
172
210
 
173
- super(self.class.fill_in_defaults(attributes))
211
+ # inspired by https://github.com/rails/rails/blob/8015c2c2cf5c8718449677570f372ceb01318a32/activemodel/lib/active_model/attributes.rb
212
+ def initialize_dup(other) # :nodoc:
213
+ @attributes = @attributes.deep_dup
214
+ super
174
215
  end
175
216
 
176
217
  def attributes
@@ -208,6 +249,11 @@ module AttrJson
208
249
  self.class.attr_json_registry.has_attribute?(str)
209
250
  end
210
251
 
252
+ # like the ActiveModel::Attributes method
253
+ def attribute_names
254
+ self.class.attribute_names
255
+ end
256
+
211
257
  # Override from ActiveModel::Serialization to #serialize
212
258
  # by type to make sure any values set directly on hash still
213
259
  # get properly type-serialized.
@@ -240,12 +286,9 @@ module AttrJson
240
286
  end
241
287
 
242
288
  # Two AttrJson::Model objects are equal if they are the same class
243
- # or one is a subclass of the other, AND their #attributes are equal.
244
- # TODO: Should we allow subclasses to be equal, or should they have to be the
245
- # exact same class?
289
+ # AND their #attributes are equal.
246
290
  def ==(other_object)
247
- (other_object.is_a?(self.class) || self.is_a?(other_object.class)) &&
248
- other_object.attributes == self.attributes
291
+ other_object.class == self.class && other_object.attributes == self.attributes
249
292
  end
250
293
 
251
294
  # ActiveRecord objects [have a](https://github.com/rails/rails/blob/v5.1.5/activerecord/lib/active_record/nested_attributes.rb#L367-L374)
@@ -257,8 +300,25 @@ module AttrJson
257
300
  false
258
301
  end
259
302
 
303
+ # like ActiveModel::Attributes at
304
+ # https://github.com/rails/rails/blob/8015c2c2cf5c8718449677570f372ceb01318a32/activemodel/lib/active_model/attributes.rb#L120
305
+ #
306
+ # is not a full deep freeze
307
+ def freeze
308
+ attributes.freeze unless frozen?
309
+ super
310
+ end
311
+
260
312
  private
261
313
 
314
+ def fill_in_defaults!
315
+ self.class.attr_json_registry.definitions.each do |definition|
316
+ if definition.has_default? && !attributes.has_key?(definition.name.to_s)
317
+ self.send("#{definition.name.to_s}=", definition.provide_default!)
318
+ end
319
+ end
320
+ end
321
+
262
322
  def _attr_json_write(key, value)
263
323
  if attribute_def = self.class.attr_json_registry[key.to_sym]
264
324
  attributes[key.to_s] = attribute_def.cast(value)
@@ -270,7 +270,13 @@ module AttrJson
270
270
  # find it from currently declared attributes.
271
271
  # https://github.com/rails/rails/blob/6aa5cf03ea8232180ffbbae4c130b051f813c670/activemodel/lib/active_model/attribute_methods.rb#L463-L468
272
272
  def matched_attribute_method(method_name)
273
- matches = self.class.send(:attribute_method_matchers_matching, method_name)
273
+ if self.class.respond_to?(:attribute_method_patterns_matching, true)
274
+ # Rails 7.1+
275
+ matches = self.class.send(:attribute_method_patterns_matching, method_name)
276
+ else
277
+ matches = self.class.send(:attribute_method_matchers_matching, method_name)
278
+ end
279
+
274
280
  matches.detect do |match|
275
281
  registry.has_attribute?(match.attr_name)
276
282
  end
@@ -10,6 +10,20 @@ module AttrJson
10
10
  end
11
11
 
12
12
  def contains_relation
13
+ contains_relation_impl do |relation, query, params|
14
+ relation.where(query, params)
15
+ end
16
+ end
17
+
18
+ def contains_not_relation
19
+ contains_relation_impl do |relation, query, params|
20
+ relation.where.not(query, params)
21
+ end
22
+ end
23
+
24
+ protected
25
+
26
+ def contains_relation_impl
13
27
  result_relation = relation
14
28
 
15
29
  group_attributes_by_container.each do |container_attribute, attributes|
@@ -18,14 +32,12 @@ module AttrJson
18
32
  attributes.each do |key, value|
19
33
  add_to_param_hash!(param_hash, key, value)
20
34
  end
21
- result_relation = result_relation.where("#{relation.table_name}.#{container_attribute} @> (?)::jsonb", param_hash.to_json)
35
+ result_relation = yield(result_relation, "#{relation.table_name}.#{container_attribute} @> (?)::jsonb", param_hash.to_json)
22
36
  end
23
37
 
24
38
  result_relation
25
39
  end
26
40
 
27
- protected
28
-
29
41
  def merge_param_hash!(original, new)
30
42
  original.deep_merge!(new) do |key, old_val, new_val|
31
43
  if old_val.is_a?(Array) && old_val.first.is_a?(Hash) && new_val.is_a?(Array) && new_val.first.is_a?(Hash)
@@ -17,6 +17,8 @@ module AttrJson
17
17
  #
18
18
  # some_model.jsonb_contains(a_string: "foo").first
19
19
  #
20
+ # some_model.not_jsonb_contains(a_string: "bar").first
21
+ #
20
22
  # See more in {file:README} docs.
21
23
  module QueryScopes
22
24
  extend ActiveSupport::Concern
@@ -29,6 +31,10 @@ module AttrJson
29
31
  scope(:jsonb_contains, lambda do |attributes|
30
32
  QueryBuilder.new(self, attributes).contains_relation
31
33
  end)
34
+
35
+ scope(:not_jsonb_contains, lambda do |attributes|
36
+ QueryBuilder.new(self, attributes).contains_not_relation
37
+ end)
32
38
  end
33
39
  end
34
40
  end
@@ -47,7 +47,7 @@ module AttrJson
47
47
  when false, nil, ActiveModel::Type::Boolean::FALSE_VALUES
48
48
  false
49
49
  else
50
- if value.respond_to?(:to_i) && ( Numeric === value || value !~ /[^0-9]/ )
50
+ if value.respond_to?(:to_i) && ( Numeric === value || value.to_s !~ /[^0-9]/ )
51
51
  !value.to_i.zero?
52
52
  elsif value.respond_to?(:zero?)
53
53
  !value.zero?
@@ -119,10 +119,11 @@ module AttrJson
119
119
  # @option options [Boolean] :rails_attribute (false) Create an actual ActiveRecord
120
120
  # `attribute` for name param. A Rails attribute isn't needed for our functionality,
121
121
  # but registering thusly will let the type be picked up by simple_form and
122
- # 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)`
123
124
  def attr_json(name, type, **options)
124
125
  options = {
125
- rails_attribute: false,
126
+ rails_attribute: self.attr_json_config.default_rails_attribute,
126
127
  validate: true,
127
128
  container_attribute: self.attr_json_config.default_container_attribute,
128
129
  accepts_nested_attributes: self.attr_json_config.default_accepts_nested_attributes
@@ -160,7 +161,21 @@ module AttrJson
160
161
  # We don't actually use this for anything, we provide our own covers. But registering
161
162
  # it with usual system will let simple_form and maybe others find it.
162
163
  if options[:rails_attribute]
163
- 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
164
179
  end
165
180
 
166
181
  _attr_jsons_module.module_eval do
@@ -173,6 +188,7 @@ module AttrJson
173
188
  # this simple way.
174
189
 
175
190
  define_method("#{name}=") do |value|
191
+ super(value) if defined?(super)
176
192
  attribute_def = self.class.attr_json_registry.fetch(name.to_sym)
177
193
  public_send(attribute_def.container_attribute)[attribute_def.store_key] = attribute_def.cast(value)
178
194
  end
@@ -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
@@ -7,6 +7,7 @@ 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
11
12
  class BadCast < ArgumentError ; end
12
13
 
@@ -31,15 +32,17 @@ module AttrJson
31
32
  # to_hash is actually the 'implicit' conversion, it really is a hash
32
33
  # even though it isn't is_a?(Hash), try to_hash first before to_h,
33
34
  # the explicit conversion.
34
- model.new_from_serializable(v.to_hash)
35
+ model.new(v.to_hash)
35
36
  elsif v.respond_to?(:to_h)
36
37
  # TODO Maybe we ought not to do this on #to_h?
37
- model.new_from_serializable(v.to_h)
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.
44
+ nil
38
45
  else
39
- # Bad input. Originally we were trying to return nil, to be like
40
- # existing ActiveRecord which kind of silently does a basic value
41
- # with null input. But that ended up making things confusing, let's
42
- # just raise.
43
46
  raise BadCast.new("Can not cast from #{v.inspect} to #{self.type}")
44
47
  end
45
48
  end
@@ -50,12 +53,36 @@ module AttrJson
50
53
  elsif v.kind_of?(model)
51
54
  v.serializable_hash
52
55
  else
53
- cast(v).serializable_hash
56
+ (cast_v = cast(v)) && cast_v.serializable_hash
54
57
  end
55
58
  end
56
59
 
57
60
  def deserialize(v)
58
- 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
59
86
  end
60
87
 
61
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.7.0"
2
+ VERSION = "1.5.0"
3
3
  end
data/lib/attr_json.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  require "attr_json/version"
2
2
 
3
3
  require "active_record"
4
- require "active_record/connection_adapters/postgresql_adapter"
5
4
 
6
5
  require 'attr_json/config'
7
6
  require 'attr_json/record'