duck_record 0.0.13 → 0.0.14

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
  SHA1:
3
- metadata.gz: a40d7265442d33cb9b0523abc991f2425c3d87ff
4
- data.tar.gz: 266ba229695849261a975fd2924cc9837a095671
3
+ metadata.gz: 1dab749c33860b97f56557d60be5eb235afe659f
4
+ data.tar.gz: fc755f0d4c244a248a9a030ae5354e3d2dc2645b
5
5
  SHA512:
6
- metadata.gz: 363119060b6e6191f6fe401a121c6548b2ca3ae28f5875a95db30aaffbb29d952c8baa0a6a37f3deb4085a24389af87c4b698eb950bcf9b9a46c1761a1a82721
7
- data.tar.gz: bc7e1560401aa6afebc76066457085b1b0898e04b69feff43cf7d4ae72693bfe164022c604575752463941360b4ca8bed5ff868d90ad4e7bf0764bc92570c1bd
6
+ metadata.gz: 79d0c5715448f98ff7702253d5b26f6338fb5f51faec2b36e8a2c7151f5f13989919518b887e1dd94712f59ca4e742dd975ac96a5dfa170f3d17dc15a09b0e01
7
+ data.tar.gz: 57b4d1113ea3accb7672f3fdd834f23d5e5934fc4b4e21400e640fe7b5fa458ff300dbb84068fad889fbe90bc235ee8166ec6c52e86449847153bc428e39cba9
data/lib/duck_record.rb CHANGED
@@ -11,10 +11,13 @@ module DuckRecord
11
11
  extend ActiveSupport::Autoload
12
12
 
13
13
  autoload :Attribute
14
+ autoload :AttributeDecorators
14
15
  autoload :Base
15
16
  autoload :Callbacks
16
17
  autoload :Core
18
+ autoload :Enum
17
19
  autoload :Inheritance
20
+ autoload :Persistence
18
21
  autoload :ModelSchema
19
22
  autoload :NestedAttributes
20
23
  autoload :ReadonlyAttributes
@@ -32,6 +35,11 @@ module DuckRecord
32
35
  autoload :NestedValidateAssociation
33
36
  end
34
37
 
38
+ module Coders
39
+ autoload :YAMLColumn, "duck_record/coders/yaml_column"
40
+ autoload :JSON, "duck_record/coders/json"
41
+ end
42
+
35
43
  module AttributeMethods
36
44
  extend ActiveSupport::Autoload
37
45
 
@@ -39,6 +47,7 @@ module DuckRecord
39
47
  autoload :BeforeTypeCast
40
48
  autoload :Dirty
41
49
  autoload :Read
50
+ autoload :Serialization
42
51
  autoload :Write
43
52
  end
44
53
  end
@@ -0,0 +1,89 @@
1
+ module DuckRecord
2
+ module AttributeDecorators # :nodoc:
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ class_attribute :attribute_type_decorations, instance_accessor: false # :internal:
7
+ self.attribute_type_decorations = TypeDecorator.new
8
+ end
9
+
10
+ module ClassMethods # :nodoc:
11
+ # This method is an internal API used to create class macros such as
12
+ # +serialize+, and features like time zone aware attributes.
13
+ #
14
+ # Used to wrap the type of an attribute in a new type.
15
+ # When the schema for a model is loaded, attributes with the same name as
16
+ # +column_name+ will have their type yielded to the given block. The
17
+ # return value of that block will be used instead.
18
+ #
19
+ # Subsequent calls where +column_name+ and +decorator_name+ are the same
20
+ # will override the previous decorator, not decorate twice. This can be
21
+ # used to create idempotent class macros like +serialize+
22
+ def decorate_attribute_type(column_name, decorator_name, &block)
23
+ matcher = ->(name, _) { name == column_name.to_s }
24
+ key = "_#{column_name}_#{decorator_name}"
25
+ decorate_matching_attribute_types(matcher, key, &block)
26
+ end
27
+
28
+ # This method is an internal API used to create higher level features like
29
+ # time zone aware attributes.
30
+ #
31
+ # When the schema for a model is loaded, +matcher+ will be called for each
32
+ # attribute with its name and type. If the matcher returns a truthy value,
33
+ # the type will then be yielded to the given block, and the return value
34
+ # of that block will replace the type.
35
+ #
36
+ # Subsequent calls to this method with the same value for +decorator_name+
37
+ # will replace the previous decorator, not decorate twice. This can be
38
+ # used to ensure that class macros are idempotent.
39
+ def decorate_matching_attribute_types(matcher, decorator_name, &block)
40
+ reload_schema_from_cache
41
+ decorator_name = decorator_name.to_s
42
+
43
+ # Create new hashes so we don't modify parent classes
44
+ self.attribute_type_decorations = attribute_type_decorations.merge(decorator_name => [matcher, block])
45
+ end
46
+
47
+ private
48
+
49
+ def load_schema!
50
+ super
51
+ attribute_types.each do |name, type|
52
+ decorated_type = attribute_type_decorations.apply(name, type)
53
+ define_attribute(name, decorated_type)
54
+ end
55
+ end
56
+ end
57
+
58
+ class TypeDecorator # :nodoc:
59
+ delegate :clear, to: :@decorations
60
+
61
+ def initialize(decorations = {})
62
+ @decorations = decorations
63
+ end
64
+
65
+ def merge(*args)
66
+ TypeDecorator.new(@decorations.merge(*args))
67
+ end
68
+
69
+ def apply(name, type)
70
+ decorations = decorators_for(name, type)
71
+ decorations.inject(type) do |new_type, block|
72
+ block.call(new_type)
73
+ end
74
+ end
75
+
76
+ private
77
+
78
+ def decorators_for(name, type)
79
+ matching(name, type).map(&:last)
80
+ end
81
+
82
+ def matching(name, type)
83
+ @decorations.values.select do |(matcher, _)|
84
+ matcher.call(name, type)
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,66 @@
1
+ module DuckRecord
2
+ module AttributeMethods
3
+ module Serialization
4
+ extend ActiveSupport::Concern
5
+
6
+ module ClassMethods
7
+ # If you have an attribute that needs to be saved to the database as an
8
+ # object, and retrieved as the same object, then specify the name of that
9
+ # attribute using this method and it will be handled automatically. The
10
+ # serialization is done through YAML. If +class_name+ is specified, the
11
+ # serialized object must be of that class on assignment and retrieval.
12
+ # Otherwise SerializationTypeMismatch will be raised.
13
+ #
14
+ # Empty objects as <tt>{}</tt>, in the case of +Hash+, or <tt>[]</tt>, in the case of
15
+ # +Array+, will always be persisted as null.
16
+ #
17
+ # Keep in mind that database adapters handle certain serialization tasks
18
+ # for you. For instance: +json+ and +jsonb+ types in PostgreSQL will be
19
+ # converted between JSON object/array syntax and Ruby +Hash+ or +Array+
20
+ # objects transparently. There is no need to use #serialize in this
21
+ # case.
22
+ #
23
+ # For more complex cases, such as conversion to or from your application
24
+ # domain objects, consider using the ActiveRecord::Attributes API.
25
+ #
26
+ # ==== Parameters
27
+ #
28
+ # * +attr_name+ - The field name that should be serialized.
29
+ # * +class_name_or_coder+ - Optional, a coder object, which responds to +.load+ and +.dump+
30
+ # or a class name that the object type should be equal to.
31
+ #
32
+ # ==== Example
33
+ #
34
+ # # Serialize a preferences attribute.
35
+ # class User < ActiveRecord::Base
36
+ # serialize :preferences
37
+ # end
38
+ #
39
+ # # Serialize preferences using JSON as coder.
40
+ # class User < ActiveRecord::Base
41
+ # serialize :preferences, JSON
42
+ # end
43
+ #
44
+ # # Serialize preferences as Hash using YAML coder.
45
+ # class User < ActiveRecord::Base
46
+ # serialize :preferences, Hash
47
+ # end
48
+ def serialize(attr_name, class_name_or_coder = Object)
49
+ # When ::JSON is used, force it to go through the Active Support JSON encoder
50
+ # to ensure special objects (e.g. Active Record models) are dumped correctly
51
+ # using the #as_json hook.
52
+ coder = if class_name_or_coder == ::JSON
53
+ Coders::JSON
54
+ elsif [:load, :dump].all? { |x| class_name_or_coder.respond_to?(x) }
55
+ class_name_or_coder
56
+ else
57
+ Coders::YAMLColumn.new(attr_name, class_name_or_coder)
58
+ end
59
+ decorate_attribute_type(attr_name, :serialize) do |type|
60
+ Type::Serialized.new(type, coder)
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -6,8 +6,8 @@ module DuckRecord
6
6
  extend ActiveSupport::Concern
7
7
 
8
8
  included do
9
- class_attribute :attributes_to_define, instance_accessor: false # :internal:
10
- self.attributes_to_define = {}
9
+ class_attribute :attributes_to_define_after_schema_loads, instance_accessor: false # :internal:
10
+ self.attributes_to_define_after_schema_loads = {}
11
11
  end
12
12
 
13
13
  module ClassMethods
@@ -193,9 +193,10 @@ module DuckRecord
193
193
  # methods in ActiveModel::Type::Value for more details.
194
194
  def attribute(name, cast_type = Type::Value.new, **options)
195
195
  name = name.to_s
196
+ reload_schema_from_cache
196
197
 
197
- self.attributes_to_define =
198
- attributes_to_define.merge(
198
+ self.attributes_to_define_after_schema_loads =
199
+ attributes_to_define_after_schema_loads.merge(
199
200
  name => [cast_type, options]
200
201
  )
201
202
  end
@@ -229,7 +230,7 @@ module DuckRecord
229
230
 
230
231
  def load_schema! # :nodoc:
231
232
  super
232
- attributes_to_define.each do |name, (type, options)|
233
+ attributes_to_define_after_schema_loads.each do |name, (type, options)|
233
234
  if type.is_a?(Symbol)
234
235
  type = DuckRecord::Type.lookup(type, **options.except(:default))
235
236
  end
@@ -274,8 +274,10 @@ module DuckRecord #:nodoc:
274
274
  extend ActiveSupport::DescendantsTracker
275
275
 
276
276
  extend Translation
277
+ extend Enum
277
278
 
278
279
  include Core
280
+ include Persistence
279
281
  include ReadonlyAttributes
280
282
  include ModelSchema
281
283
  include Inheritance
@@ -283,6 +285,7 @@ module DuckRecord #:nodoc:
283
285
  include ActiveModel::Conversion
284
286
  include Validations
285
287
  include Attributes
288
+ include AttributeDecorators
286
289
  include DefineCallbacks
287
290
  include AttributeMethods
288
291
  include Callbacks
@@ -292,14 +295,6 @@ module DuckRecord #:nodoc:
292
295
  include Reflection
293
296
  include Serialization
294
297
 
295
- def persisted?
296
- false
297
- end
298
-
299
- def new_record?
300
- true
301
- end
302
-
303
298
  def to_h(include_empty: true)
304
299
  hash = serializable_hash
305
300
 
@@ -0,0 +1,13 @@
1
+ module DuckRecord
2
+ module Coders # :nodoc:
3
+ class JSON # :nodoc:
4
+ def self.dump(obj)
5
+ ActiveSupport::JSON.encode(obj)
6
+ end
7
+
8
+ def self.load(json)
9
+ ActiveSupport::JSON.decode(json) unless json.blank?
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,48 @@
1
+ require "yaml"
2
+
3
+ module DuckRecord
4
+ module Coders # :nodoc:
5
+ class YAMLColumn # :nodoc:
6
+ attr_accessor :object_class
7
+
8
+ def initialize(attr_name, object_class = Object)
9
+ @attr_name = attr_name
10
+ @object_class = object_class
11
+ check_arity_of_constructor
12
+ end
13
+
14
+ def dump(obj)
15
+ return if obj.nil?
16
+
17
+ assert_valid_value(obj, action: "dump")
18
+ YAML.dump obj
19
+ end
20
+
21
+ def load(yaml)
22
+ return object_class.new if object_class != Object && yaml.nil?
23
+ return yaml unless yaml.is_a?(String) && /^---/.match?(yaml)
24
+ obj = YAML.load(yaml)
25
+
26
+ assert_valid_value(obj, action: "load")
27
+ obj ||= object_class.new if object_class != Object
28
+
29
+ obj
30
+ end
31
+
32
+ def assert_valid_value(obj, action:)
33
+ unless obj.nil? || obj.is_a?(object_class)
34
+ raise SerializationTypeMismatch,
35
+ "can't #{action} `#{@attr_name}`: was supposed to be a #{object_class}, but was a #{obj.class}. -- #{obj.inspect}"
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def check_arity_of_constructor
42
+ load(nil)
43
+ rescue ArgumentError
44
+ raise ArgumentError, "Cannot serialize #{object_class}. Classes passed to `serialize` must have a 0 argument constructor."
45
+ end
46
+ end
47
+ end
48
+ end
@@ -45,7 +45,8 @@ module DuckRecord
45
45
  if abstract_class?
46
46
  "#{super}(abstract)"
47
47
  else
48
- super
48
+ attr_list = attribute_types.map { |name, type| "#{name}: #{type.type}" } * ", "
49
+ "#{super}(#{attr_list})"
49
50
  end
50
51
  end
51
52
  end
@@ -0,0 +1,139 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/object/deep_dup"
4
+
5
+ module DuckRecord
6
+ module Enum
7
+ def self.extended(base) # :nodoc:
8
+ base.class_attribute(:defined_enums, instance_writer: false)
9
+ base.defined_enums = {}
10
+ end
11
+
12
+ def inherited(base) # :nodoc:
13
+ base.defined_enums = defined_enums.deep_dup
14
+ super
15
+ end
16
+
17
+ class EnumType < ActiveModel::Type::Value # :nodoc:
18
+ delegate :type, to: :subtype
19
+
20
+ def initialize(name, mapping, subtype)
21
+ @name = name
22
+ @mapping = mapping
23
+ @subtype = subtype
24
+ end
25
+
26
+ def cast(value)
27
+ return if value.blank?
28
+
29
+ if mapping.has_key?(value)
30
+ value.to_s
31
+ elsif mapping.has_value?(value)
32
+ mapping.key(value)
33
+ else
34
+ assert_valid_value(value)
35
+ end
36
+ end
37
+
38
+ def deserialize(value)
39
+ return if value.nil?
40
+ mapping.key(subtype.deserialize(value))
41
+ end
42
+
43
+ def serialize(value)
44
+ mapping.fetch(value, value)
45
+ end
46
+
47
+ def assert_valid_value(value)
48
+ unless value.blank? || mapping.has_key?(value) || mapping.has_value?(value)
49
+ raise ArgumentError, "'#{value}' is not a valid #{name}"
50
+ end
51
+ end
52
+
53
+ private
54
+
55
+ attr_reader :name, :mapping, :subtype
56
+ end
57
+
58
+ def enum(definitions)
59
+ klass = self
60
+ enum_prefix = definitions.delete(:_prefix)
61
+ enum_suffix = definitions.delete(:_suffix)
62
+ definitions.each do |name, values|
63
+ # statuses = { }
64
+ enum_values = ActiveSupport::HashWithIndifferentAccess.new
65
+ name = name.to_sym
66
+
67
+ # def self.statuses() statuses end
68
+ detect_enum_conflict!(name, name.to_s.pluralize, true)
69
+ klass.singleton_class.send(:define_method, name.to_s.pluralize) { enum_values }
70
+
71
+ detect_enum_conflict!(name, name)
72
+ detect_enum_conflict!(name, "#{name}=")
73
+
74
+ attr = attribute_alias?(name) ? attribute_alias(name) : name
75
+ decorate_attribute_type(attr, :enum) do |subtype|
76
+ EnumType.new(attr, enum_values, subtype)
77
+ end
78
+
79
+ _enum_methods_module.module_eval do
80
+ pairs = values.respond_to?(:each_pair) ? values.each_pair : values.each_with_index
81
+ pairs.each do |value, i|
82
+ if enum_prefix == true
83
+ prefix = "#{name}_"
84
+ elsif enum_prefix
85
+ prefix = "#{enum_prefix}_"
86
+ end
87
+ if enum_suffix == true
88
+ suffix = "_#{name}"
89
+ elsif enum_suffix
90
+ suffix = "_#{enum_suffix}"
91
+ end
92
+
93
+ value_method_name = "#{prefix}#{value}#{suffix}"
94
+ enum_values[value] = i
95
+
96
+ # def active?() status == 0 end
97
+ klass.send(:detect_enum_conflict!, name, "#{value_method_name}?")
98
+ define_method("#{value_method_name}?") { self[attr] == value.to_s }
99
+ end
100
+ end
101
+ defined_enums[name.to_s] = enum_values
102
+ end
103
+ end
104
+
105
+ private
106
+ def _enum_methods_module
107
+ @_enum_methods_module ||= begin
108
+ mod = Module.new
109
+ include mod
110
+ mod
111
+ end
112
+ end
113
+
114
+ ENUM_CONFLICT_MESSAGE = \
115
+ "You tried to define an enum named \"%{enum}\" on the model \"%{klass}\", but " \
116
+ "this will generate a %{type} method \"%{method}\", which is already defined " \
117
+ "by %{source}."
118
+
119
+ def detect_enum_conflict!(enum_name, method_name, klass_method = false)
120
+ if klass_method && dangerous_class_method?(method_name)
121
+ raise_conflict_error(enum_name, method_name, type: "class")
122
+ elsif !klass_method && dangerous_attribute_method?(method_name)
123
+ raise_conflict_error(enum_name, method_name)
124
+ elsif !klass_method && method_defined_within?(method_name, _enum_methods_module, Module)
125
+ raise_conflict_error(enum_name, method_name, source: "another enum")
126
+ end
127
+ end
128
+
129
+ def raise_conflict_error(enum_name, method_name, type: "instance", source: "Active Record")
130
+ raise ArgumentError, ENUM_CONFLICT_MESSAGE % {
131
+ enum: enum_name,
132
+ klass: name,
133
+ type: type,
134
+ method: method_name,
135
+ source: source
136
+ }
137
+ end
138
+ end
139
+ end
@@ -53,6 +53,10 @@ module DuckRecord
53
53
  end
54
54
  end
55
55
 
56
+ # Raised when unserialized object's type mismatches one specified for serializable field.
57
+ class SerializationTypeMismatch < DuckRecordError
58
+ end
59
+
56
60
  # Raised when there are multiple errors while doing a mass assignment through the
57
61
  # {DuckRecord::Base#attributes=}[rdoc-ref:AttributeAssignment#attributes=]
58
62
  # method. The exception has an +errors+ property that contains an array of AttributeAssignmentError
@@ -9,7 +9,7 @@ module DuckRecord
9
9
  module ClassMethods
10
10
  def attribute_types # :nodoc:
11
11
  load_schema
12
- @attribute_types ||= Hash.new
12
+ @attribute_types ||= Hash.new(Type.default_value)
13
13
  end
14
14
 
15
15
  def yaml_encoder # :nodoc:
@@ -42,7 +42,7 @@ module DuckRecord
42
42
  private
43
43
 
44
44
  def schema_loaded?
45
- defined?(@loaded) && @loaded
45
+ defined?(@schema_loaded) && @schema_loaded
46
46
  end
47
47
 
48
48
  def load_schema
@@ -52,7 +52,19 @@ module DuckRecord
52
52
  end
53
53
 
54
54
  def load_schema!
55
- @loaded = true
55
+ @schema_loaded = true
56
+ end
57
+
58
+ def reload_schema_from_cache
59
+ @attribute_types = nil
60
+ @default_attributes = nil
61
+ @attributes_builder = nil
62
+ @schema_loaded = false
63
+ @attribute_names = nil
64
+ @yaml_encoder = nil
65
+ direct_descendants.each do |descendant|
66
+ descendant.send(:reload_schema_from_cache)
67
+ end
56
68
  end
57
69
  end
58
70
  end
@@ -0,0 +1,39 @@
1
+ module DuckRecord
2
+ # = DuckRecord \Persistence
3
+ module Persistence
4
+ extend ActiveSupport::Concern
5
+
6
+ def persisted?
7
+ false
8
+ end
9
+
10
+ def destroyed?
11
+ false
12
+ end
13
+
14
+ def new_record?
15
+ true
16
+ end
17
+
18
+ # Returns an instance of the specified +klass+ with the attributes of the
19
+ # current record. This is mostly useful in relation to single-table
20
+ # inheritance structures where you want a subclass to appear as the
21
+ # superclass. This can be used along with record identification in
22
+ # Action Pack to allow, say, <tt>Client < Company</tt> to do something
23
+ # like render <tt>partial: @client.becomes(Company)</tt> to render that
24
+ # instance using the companies/company partial instead of clients/client.
25
+ #
26
+ # Note: The new instance will share a link to the same attributes as the original class.
27
+ # Therefore the sti column value will still be the same.
28
+ # Any change to the attributes on either instance will affect both instances.
29
+ # If you want to change the sti column as well, use #becomes! instead.
30
+ def becomes(klass)
31
+ became = klass.new
32
+ became.instance_variable_set("@attributes", @attributes)
33
+ became.instance_variable_set("@mutation_tracker", @mutation_tracker) if defined?(@mutation_tracker)
34
+ became.instance_variable_set("@changed_attributes", attributes_changed_by_setter)
35
+ became.errors.copy!(errors)
36
+ became
37
+ end
38
+ end
39
+ end
@@ -41,6 +41,10 @@ module DuckRecord
41
41
  def lookup(*args, **kwargs) # :nodoc:
42
42
  registry.lookup(*args, **kwargs)
43
43
  end
44
+
45
+ def default_value # :nodoc:
46
+ @default_value ||= Value.new
47
+ end
44
48
  end
45
49
 
46
50
  Helpers = ActiveModel::Type::Helpers
@@ -1,3 +1,3 @@
1
1
  module DuckRecord
2
- VERSION = "0.0.13"
2
+ VERSION = "0.0.14"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: duck_record
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.13
4
+ version: 0.0.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - jasl
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-10-04 00:00:00.000000000 Z
11
+ date: 2017-12-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -97,10 +97,12 @@ files:
97
97
  - lib/duck_record/attribute.rb
98
98
  - lib/duck_record/attribute/user_provided_default.rb
99
99
  - lib/duck_record/attribute_assignment.rb
100
+ - lib/duck_record/attribute_decorators.rb
100
101
  - lib/duck_record/attribute_methods.rb
101
102
  - lib/duck_record/attribute_methods/before_type_cast.rb
102
103
  - lib/duck_record/attribute_methods/dirty.rb
103
104
  - lib/duck_record/attribute_methods/read.rb
105
+ - lib/duck_record/attribute_methods/serialization.rb
104
106
  - lib/duck_record/attribute_methods/write.rb
105
107
  - lib/duck_record/attribute_mutation_tracker.rb
106
108
  - lib/duck_record/attribute_set.rb
@@ -108,14 +110,18 @@ files:
108
110
  - lib/duck_record/attributes.rb
109
111
  - lib/duck_record/base.rb
110
112
  - lib/duck_record/callbacks.rb
113
+ - lib/duck_record/coders/json.rb
114
+ - lib/duck_record/coders/yaml_column.rb
111
115
  - lib/duck_record/core.rb
112
116
  - lib/duck_record/define_callbacks.rb
117
+ - lib/duck_record/enum.rb
113
118
  - lib/duck_record/errors.rb
114
119
  - lib/duck_record/inheritance.rb
115
120
  - lib/duck_record/locale/en.yml
116
121
  - lib/duck_record/model_schema.rb
117
122
  - lib/duck_record/nested_attributes.rb
118
123
  - lib/duck_record/nested_validate_association.rb
124
+ - lib/duck_record/persistence.rb
119
125
  - lib/duck_record/readonly_attributes.rb
120
126
  - lib/duck_record/reflection.rb
121
127
  - lib/duck_record/serialization.rb
@@ -158,7 +164,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
158
164
  version: '0'
159
165
  requirements: []
160
166
  rubyforge_project:
161
- rubygems_version: 2.6.12
167
+ rubygems_version: 2.6.13
162
168
  signing_key:
163
169
  specification_version: 4
164
170
  summary: Used for creating virtual models like ActiveType or ModelAttribute does