duck_record 0.0.16 → 0.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/lib/duck_record/associations/builder/{association.rb → embeds_association.rb} +5 -5
- data/lib/duck_record/associations/builder/{collection_association.rb → embeds_many.rb} +6 -2
- data/lib/duck_record/associations/builder/{singular_association.rb → embeds_one.rb} +13 -1
- data/lib/duck_record/associations/{association.rb → embeds_association.rb} +1 -1
- data/lib/duck_record/associations/{collection_association.rb → embeds_many_association.rb} +2 -2
- data/lib/duck_record/associations/{collection_proxy.rb → embeds_many_proxy.rb} +1 -1
- data/lib/duck_record/associations/{singular_association.rb → embeds_one_association.rb} +10 -3
- data/lib/duck_record/associations.rb +11 -892
- data/lib/duck_record/attribute_assignment.rb +16 -17
- data/lib/duck_record/attribute_methods/write.rb +19 -16
- data/lib/duck_record/base.rb +0 -20
- data/lib/duck_record/core.rb +5 -1
- data/lib/duck_record/nested_attributes.rb +1 -1
- data/lib/duck_record/nested_validate_association.rb +1 -1
- data/lib/duck_record/readonly_attributes.rb +13 -0
- data/lib/duck_record/reflection.rb +11 -11
- data/lib/duck_record/serialization.rb +5 -16
- data/lib/duck_record/version.rb +1 -1
- metadata +10 -14
- data/lib/duck_record/associations/builder/has_many.rb +0 -7
- data/lib/duck_record/associations/builder/has_one.rb +0 -15
- data/lib/duck_record/associations/has_many_association.rb +0 -11
- data/lib/duck_record/associations/has_one_association.rb +0 -17
@@ -7,23 +7,23 @@ module DuckRecord
|
|
7
7
|
include ActiveModel::ForbiddenAttributesProtection
|
8
8
|
|
9
9
|
# Alias for ActiveModel::AttributeAssignment#assign_attributes. See ActiveModel::AttributeAssignment.
|
10
|
-
def attributes=(attributes
|
11
|
-
assign_attributes(attributes
|
10
|
+
def attributes=(attributes)
|
11
|
+
assign_attributes(attributes)
|
12
12
|
end
|
13
13
|
|
14
|
-
def assign_attributes(new_attributes
|
14
|
+
def assign_attributes(new_attributes)
|
15
15
|
unless new_attributes.respond_to?(:stringify_keys)
|
16
16
|
raise ArgumentError, "When assigning attributes, you must pass a hash as an argument."
|
17
17
|
end
|
18
18
|
return if new_attributes.nil? || new_attributes.empty?
|
19
19
|
|
20
20
|
attributes = new_attributes.stringify_keys
|
21
|
-
_assign_attributes(sanitize_for_mass_assignment(attributes)
|
21
|
+
_assign_attributes(sanitize_for_mass_assignment(attributes))
|
22
22
|
end
|
23
23
|
|
24
24
|
private
|
25
25
|
|
26
|
-
def _assign_attributes(attributes
|
26
|
+
def _assign_attributes(attributes)
|
27
27
|
multi_parameter_attributes = {}
|
28
28
|
nested_parameter_attributes = {}
|
29
29
|
|
@@ -36,21 +36,21 @@ module DuckRecord
|
|
36
36
|
end
|
37
37
|
|
38
38
|
attributes.each do |k, v|
|
39
|
-
_assign_attribute(k, v
|
39
|
+
_assign_attribute(k, v)
|
40
40
|
end
|
41
41
|
|
42
42
|
unless nested_parameter_attributes.empty?
|
43
|
-
assign_nested_parameter_attributes(nested_parameter_attributes
|
43
|
+
assign_nested_parameter_attributes(nested_parameter_attributes)
|
44
44
|
end
|
45
45
|
|
46
46
|
unless multi_parameter_attributes.empty?
|
47
|
-
assign_multiparameter_attributes(multi_parameter_attributes
|
47
|
+
assign_multiparameter_attributes(multi_parameter_attributes)
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
51
|
# Assign any deferred nested attributes after the base attributes have been set.
|
52
|
-
def assign_nested_parameter_attributes(pairs
|
53
|
-
pairs.each { |k, v| _assign_attribute(k, v
|
52
|
+
def assign_nested_parameter_attributes(pairs)
|
53
|
+
pairs.each { |k, v| _assign_attribute(k, v) }
|
54
54
|
end
|
55
55
|
|
56
56
|
# Instantiates objects for all attribute classes that needs more than one constructor parameter. This is done
|
@@ -59,14 +59,13 @@ module DuckRecord
|
|
59
59
|
# written_on (a date type) with Date.new("2004", "6", "24"). You can also specify a typecast character in the
|
60
60
|
# parentheses to have the parameters typecasted before they're used in the constructor. Use i for Integer and
|
61
61
|
# f for Float. If all the values for a given attribute are empty, the attribute will be set to +nil+.
|
62
|
-
def assign_multiparameter_attributes(pairs
|
62
|
+
def assign_multiparameter_attributes(pairs)
|
63
63
|
execute_callstack_for_multiparameter_attributes(
|
64
|
-
extract_callstack_for_multiparameter_attributes(pairs)
|
65
|
-
force_write_readonly: force_write_readonly
|
64
|
+
extract_callstack_for_multiparameter_attributes(pairs)
|
66
65
|
)
|
67
66
|
end
|
68
67
|
|
69
|
-
def execute_callstack_for_multiparameter_attributes(callstack
|
68
|
+
def execute_callstack_for_multiparameter_attributes(callstack)
|
70
69
|
errors = []
|
71
70
|
callstack.each do |name, values_with_empty_parameters|
|
72
71
|
begin
|
@@ -75,7 +74,7 @@ module DuckRecord
|
|
75
74
|
else
|
76
75
|
values = values_with_empty_parameters
|
77
76
|
end
|
78
|
-
send("#{name}=", values
|
77
|
+
send("#{name}=", values)
|
79
78
|
rescue => ex
|
80
79
|
errors << AttributeAssignmentError.new("error on assignment #{values_with_empty_parameters.values.inspect} to #{name} (#{ex.message})", ex, name)
|
81
80
|
end
|
@@ -108,9 +107,9 @@ module DuckRecord
|
|
108
107
|
multiparameter_name.scan(/\(([0-9]*).*\)/).first.first.to_i
|
109
108
|
end
|
110
109
|
|
111
|
-
def _assign_attribute(k, v
|
110
|
+
def _assign_attribute(k, v)
|
112
111
|
if respond_to?("#{k}=")
|
113
|
-
public_send("#{k}=", v
|
112
|
+
public_send("#{k}=", v)
|
114
113
|
else
|
115
114
|
raise UnknownAttributeError.new(self, k)
|
116
115
|
end
|
@@ -15,9 +15,9 @@ module DuckRecord
|
|
15
15
|
DuckRecord::AttributeMethods::AttrNames.set_name_cache safe_name, name
|
16
16
|
|
17
17
|
generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
|
18
|
-
def __temp__#{safe_name}=(value
|
18
|
+
def __temp__#{safe_name}=(value)
|
19
19
|
name = ::DuckRecord::AttributeMethods::AttrNames::ATTR_#{safe_name}
|
20
|
-
write_attribute(name, value
|
20
|
+
write_attribute(name, value)
|
21
21
|
end
|
22
22
|
alias_method #{(name + '=').inspect}, :__temp__#{safe_name}=
|
23
23
|
undef_method :__temp__#{safe_name}=
|
@@ -28,32 +28,35 @@ module DuckRecord
|
|
28
28
|
# Updates the attribute identified by <tt>attr_name</tt> with the
|
29
29
|
# specified +value+. Empty strings for Integer and Float columns are
|
30
30
|
# turned into +nil+.
|
31
|
-
def write_attribute(attr_name, value
|
32
|
-
name =
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
31
|
+
def write_attribute(attr_name, value)
|
32
|
+
name =
|
33
|
+
if self.class.attribute_alias?(attr_name)
|
34
|
+
self.class.attribute_alias(attr_name).to_s
|
35
|
+
else
|
36
|
+
attr_name.to_s
|
37
|
+
end
|
37
38
|
|
38
|
-
|
39
|
+
if self.class.readonly_attributes.include?(name) && attr_readonly_enabled?
|
40
|
+
return
|
41
|
+
end
|
42
|
+
|
43
|
+
write_attribute_with_type_cast(name, value, true)
|
39
44
|
end
|
40
45
|
|
41
|
-
def raw_write_attribute(attr_name, value
|
42
|
-
write_attribute_with_type_cast(attr_name, value, false
|
46
|
+
def raw_write_attribute(attr_name, value) # :nodoc:
|
47
|
+
write_attribute_with_type_cast(attr_name, value, false)
|
43
48
|
end
|
44
49
|
|
45
50
|
private
|
46
51
|
|
47
52
|
# Handle *= for method_missing.
|
48
|
-
def attribute=(attribute_name, value
|
49
|
-
write_attribute(attribute_name, value
|
53
|
+
def attribute=(attribute_name, value)
|
54
|
+
write_attribute(attribute_name, value)
|
50
55
|
end
|
51
56
|
|
52
|
-
def write_attribute_with_type_cast(attr_name, value, should_type_cast
|
57
|
+
def write_attribute_with_type_cast(attr_name, value, should_type_cast)
|
53
58
|
attr_name = attr_name.to_s
|
54
59
|
|
55
|
-
return if !force_write_readonly && self.class.readonly_attributes.include?(attr_name)
|
56
|
-
|
57
60
|
if should_type_cast
|
58
61
|
@attributes.write_from_user(attr_name, value)
|
59
62
|
else
|
data/lib/duck_record/base.rb
CHANGED
@@ -294,26 +294,6 @@ module DuckRecord #:nodoc:
|
|
294
294
|
include NestedAttributes
|
295
295
|
include Reflection
|
296
296
|
include Serialization
|
297
|
-
|
298
|
-
def to_h(include_empty: true)
|
299
|
-
hash = serializable_hash
|
300
|
-
|
301
|
-
self.class.reflections.keys.each do |k|
|
302
|
-
records = send(k)
|
303
|
-
sub_hash =
|
304
|
-
if records.respond_to?(:to_ary)
|
305
|
-
records.to_ary.map { |a| a.to_h }
|
306
|
-
else
|
307
|
-
records.to_h
|
308
|
-
end
|
309
|
-
|
310
|
-
if include_empty || sub_hash.any?
|
311
|
-
hash[k] = sub_hash
|
312
|
-
end
|
313
|
-
end
|
314
|
-
|
315
|
-
hash
|
316
|
-
end
|
317
297
|
end
|
318
298
|
|
319
299
|
ActiveSupport.run_load_hooks(:duck_record, Base)
|
data/lib/duck_record/core.rb
CHANGED
@@ -63,16 +63,20 @@ module DuckRecord
|
|
63
63
|
self.class.define_attribute_methods
|
64
64
|
@attributes = self.class._default_attributes.deep_dup
|
65
65
|
|
66
|
+
disable_attr_readonly!
|
67
|
+
|
66
68
|
init_internals
|
67
69
|
initialize_internals_callback
|
68
70
|
|
69
71
|
if attributes
|
70
|
-
assign_attributes(attributes
|
72
|
+
assign_attributes(attributes)
|
71
73
|
clear_changes_information
|
72
74
|
end
|
73
75
|
|
74
76
|
yield self if block_given?
|
75
77
|
_run_initialize_callbacks
|
78
|
+
|
79
|
+
enable_attr_readonly!
|
76
80
|
end
|
77
81
|
|
78
82
|
# Initialize an empty model object from +coder+. +coder+ should be
|
@@ -356,7 +356,7 @@ module DuckRecord
|
|
356
356
|
if method_defined?(:#{association_name}_attributes=)
|
357
357
|
remove_method(:#{association_name}_attributes=)
|
358
358
|
end
|
359
|
-
def #{association_name}_attributes=(attributes
|
359
|
+
def #{association_name}_attributes=(attributes)
|
360
360
|
assign_nested_attributes_for_#{type}_association(:#{association_name}, attributes)
|
361
361
|
end
|
362
362
|
eoruby
|
@@ -139,7 +139,7 @@ module DuckRecord
|
|
139
139
|
end
|
140
140
|
|
141
141
|
included do
|
142
|
-
Associations::Builder::
|
142
|
+
Associations::Builder::EmbedsAssociation.extensions << AssociationBuilderExtension
|
143
143
|
mattr_accessor :index_nested_attribute_errors, instance_writer: false
|
144
144
|
self.index_nested_attribute_errors = false
|
145
145
|
end
|
@@ -3,10 +3,23 @@ module DuckRecord
|
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
5
|
included do
|
6
|
+
attr_accessor :_attr_readonly_enabled
|
6
7
|
class_attribute :_attr_readonly, instance_accessor: false
|
7
8
|
self._attr_readonly = []
|
8
9
|
end
|
9
10
|
|
11
|
+
def attr_readonly_enabled?
|
12
|
+
_attr_readonly_enabled
|
13
|
+
end
|
14
|
+
|
15
|
+
def enable_attr_readonly!
|
16
|
+
self._attr_readonly_enabled = true
|
17
|
+
end
|
18
|
+
|
19
|
+
def disable_attr_readonly!
|
20
|
+
self._attr_readonly_enabled = false
|
21
|
+
end
|
22
|
+
|
10
23
|
module ClassMethods
|
11
24
|
# Attributes listed as readonly will be used to create a new record but update operations will
|
12
25
|
# ignore these fields.
|
@@ -15,10 +15,10 @@ module DuckRecord
|
|
15
15
|
def self.create(macro, name, options, ar)
|
16
16
|
klass = \
|
17
17
|
case macro
|
18
|
-
when :
|
19
|
-
|
20
|
-
when :
|
21
|
-
|
18
|
+
when :embeds_many
|
19
|
+
EmbedsManyReflection
|
20
|
+
when :embeds_one
|
21
|
+
EmbedsOneReflection
|
22
22
|
else
|
23
23
|
raise "Unsupported Macro: #{macro}"
|
24
24
|
end
|
@@ -182,7 +182,7 @@ module DuckRecord
|
|
182
182
|
|
183
183
|
# Holds all the metadata about an association as it was specified in the
|
184
184
|
# Active Record class.
|
185
|
-
class
|
185
|
+
class EmbedsAssociationReflection < MacroReflection #:nodoc:
|
186
186
|
# Returns the target association's class.
|
187
187
|
#
|
188
188
|
# class Author < ActiveRecord::Base
|
@@ -286,23 +286,23 @@ module DuckRecord
|
|
286
286
|
end
|
287
287
|
end
|
288
288
|
|
289
|
-
class
|
290
|
-
def macro; :
|
289
|
+
class EmbedsManyReflection < EmbedsAssociationReflection # :nodoc:
|
290
|
+
def macro; :embeds_many; end
|
291
291
|
|
292
292
|
def collection?; true; end
|
293
293
|
|
294
294
|
def association_class
|
295
|
-
Associations::
|
295
|
+
Associations::EmbedsManyAssociation
|
296
296
|
end
|
297
297
|
end
|
298
298
|
|
299
|
-
class
|
300
|
-
def macro; :
|
299
|
+
class EmbedsOneReflection < EmbedsAssociationReflection # :nodoc:
|
300
|
+
def macro; :embeds_one; end
|
301
301
|
|
302
302
|
def has_one?; true; end
|
303
303
|
|
304
304
|
def association_class
|
305
|
-
Associations::
|
305
|
+
Associations::EmbedsOneAssociation
|
306
306
|
end
|
307
307
|
end
|
308
308
|
end
|
@@ -8,24 +8,13 @@ module DuckRecord #:nodoc:
|
|
8
8
|
self.include_root_in_json = false
|
9
9
|
end
|
10
10
|
|
11
|
-
def serializable_hash(options =
|
12
|
-
options = (
|
13
|
-
super options
|
14
|
-
end
|
11
|
+
def serializable_hash(options = nil)
|
12
|
+
options = options.try(:dup) || {}
|
15
13
|
|
16
|
-
|
14
|
+
options[:except] = Array(options[:except]).map(&:to_s)
|
15
|
+
options[:include] = Array(_reflections.keys).map(&:to_s)
|
17
16
|
|
18
|
-
|
19
|
-
v = send(key)
|
20
|
-
if v.respond_to?(:serializable_hash)
|
21
|
-
v.serializable_hash
|
22
|
-
elsif v.respond_to?(:to_ary)
|
23
|
-
v.to_ary
|
24
|
-
elsif v.respond_to?(:to_hash)
|
25
|
-
v.to_hash
|
26
|
-
else
|
27
|
-
v
|
28
|
-
end
|
17
|
+
super(options)
|
29
18
|
end
|
30
19
|
end
|
31
20
|
end
|
data/lib/duck_record/version.rb
CHANGED
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.
|
4
|
+
version: 0.0.18
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- jasl
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-12-
|
11
|
+
date: 2017-12-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -83,17 +83,13 @@ files:
|
|
83
83
|
- lib/core_ext/array_without_blank.rb
|
84
84
|
- lib/duck_record.rb
|
85
85
|
- lib/duck_record/associations.rb
|
86
|
-
- lib/duck_record/associations/
|
87
|
-
- lib/duck_record/associations/builder/
|
88
|
-
- lib/duck_record/associations/builder/
|
89
|
-
- lib/duck_record/associations/
|
90
|
-
- lib/duck_record/associations/
|
91
|
-
- lib/duck_record/associations/
|
92
|
-
- lib/duck_record/associations/
|
93
|
-
- lib/duck_record/associations/collection_proxy.rb
|
94
|
-
- lib/duck_record/associations/has_many_association.rb
|
95
|
-
- lib/duck_record/associations/has_one_association.rb
|
96
|
-
- lib/duck_record/associations/singular_association.rb
|
86
|
+
- lib/duck_record/associations/builder/embeds_association.rb
|
87
|
+
- lib/duck_record/associations/builder/embeds_many.rb
|
88
|
+
- lib/duck_record/associations/builder/embeds_one.rb
|
89
|
+
- lib/duck_record/associations/embeds_association.rb
|
90
|
+
- lib/duck_record/associations/embeds_many_association.rb
|
91
|
+
- lib/duck_record/associations/embeds_many_proxy.rb
|
92
|
+
- lib/duck_record/associations/embeds_one_association.rb
|
97
93
|
- lib/duck_record/attribute.rb
|
98
94
|
- lib/duck_record/attribute/user_provided_default.rb
|
99
95
|
- lib/duck_record/attribute_assignment.rb
|
@@ -164,7 +160,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
164
160
|
version: '0'
|
165
161
|
requirements: []
|
166
162
|
rubyforge_project:
|
167
|
-
rubygems_version: 2.6.
|
163
|
+
rubygems_version: 2.6.12
|
168
164
|
signing_key:
|
169
165
|
specification_version: 4
|
170
166
|
summary: Used for creating virtual models like ActiveType or ModelAttribute does
|
@@ -1,15 +0,0 @@
|
|
1
|
-
module DuckRecord::Associations::Builder # :nodoc:
|
2
|
-
class HasOne < SingularAssociation #:nodoc:
|
3
|
-
def self.macro
|
4
|
-
:has_one
|
5
|
-
end
|
6
|
-
|
7
|
-
def self.define_validations(model, reflection)
|
8
|
-
super
|
9
|
-
|
10
|
-
if reflection.options[:required]
|
11
|
-
model.validates_presence_of reflection.name, message: :required
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
@@ -1,11 +0,0 @@
|
|
1
|
-
module DuckRecord
|
2
|
-
# = Active Record Has Many Association
|
3
|
-
module Associations
|
4
|
-
# This is the proxy that handles a has many association.
|
5
|
-
#
|
6
|
-
# If the association has a <tt>:through</tt> option further specialization
|
7
|
-
# is provided by its child HasManyThroughAssociation.
|
8
|
-
class HasManyAssociation < CollectionAssociation #:nodoc:
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
module DuckRecord
|
2
|
-
# = Active Record Has One Association
|
3
|
-
module Associations
|
4
|
-
class HasOneAssociation < SingularAssociation #:nodoc:
|
5
|
-
def replace(record)
|
6
|
-
self.target =
|
7
|
-
if record.is_a? klass
|
8
|
-
record
|
9
|
-
elsif record.respond_to?(:to_h)
|
10
|
-
build_record(record.to_h)
|
11
|
-
end
|
12
|
-
rescue
|
13
|
-
raise_on_type_mismatch!(record)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|