duck_record 0.0.16 → 0.0.18
Sign up to get free protection for your applications and to get access to all the features.
- 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
|