duck_record 0.0.7 → 0.0.8
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/lib/duck_record/attribute_assignment.rb +41 -13
- data/lib/duck_record/attribute_methods/write.rb +15 -13
- data/lib/duck_record/base.rb +1 -0
- data/lib/duck_record/core.rb +1 -1
- data/lib/duck_record/readonly_attributes.rb +23 -0
- data/lib/duck_record/version.rb +1 -1
- data/lib/duck_record.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 26cdafb4677192d3b19b66b6c691f739e6dc70ae
|
4
|
+
data.tar.gz: 5c1e47c06bece7781a4812389dbc7218ae240ed1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ddf042c24da96f908e7dcb8183566574a7208e02da658e8cf023a8e729e63019a9a659c66a7f782ed8055842f7b45ac5fa74a690bd3d91b2e6901e428a474ee6
|
7
|
+
data.tar.gz: 6a63e7f449a1815fc742fc93530f90407645bb6d1b51ff5382dc4b6102e4dacd4eeb113b82a49c8125e972289a5ab8c856680dc0ceeabe9db927458c8e47a6ba
|
@@ -1,18 +1,29 @@
|
|
1
|
+
require 'active_support/core_ext/hash/keys'
|
1
2
|
require 'active_model/forbidden_attributes_protection'
|
2
3
|
|
3
4
|
module DuckRecord
|
4
5
|
module AttributeAssignment
|
5
6
|
extend ActiveSupport::Concern
|
6
|
-
include ActiveModel::
|
7
|
+
include ActiveModel::ForbiddenAttributesProtection
|
7
8
|
|
8
9
|
# Alias for ActiveModel::AttributeAssignment#assign_attributes. See ActiveModel::AttributeAssignment.
|
9
|
-
def attributes=(attributes)
|
10
|
-
assign_attributes(attributes)
|
10
|
+
def attributes=(attributes, force_write_readonly: false)
|
11
|
+
assign_attributes(attributes, force_write_readonly: force_write_readonly)
|
12
|
+
end
|
13
|
+
|
14
|
+
def assign_attributes(new_attributes, force_write_readonly: false)
|
15
|
+
unless new_attributes.respond_to?(:stringify_keys)
|
16
|
+
raise ArgumentError, "When assigning attributes, you must pass a hash as an argument."
|
17
|
+
end
|
18
|
+
return if new_attributes.nil? || new_attributes.empty?
|
19
|
+
|
20
|
+
attributes = new_attributes.stringify_keys
|
21
|
+
_assign_attributes(sanitize_for_mass_assignment(attributes), force_write_readonly: force_write_readonly)
|
11
22
|
end
|
12
23
|
|
13
24
|
private
|
14
25
|
|
15
|
-
def _assign_attributes(attributes)
|
26
|
+
def _assign_attributes(attributes, force_write_readonly: false)
|
16
27
|
multi_parameter_attributes = {}
|
17
28
|
nested_parameter_attributes = {}
|
18
29
|
|
@@ -23,15 +34,23 @@ module DuckRecord
|
|
23
34
|
nested_parameter_attributes[k] = attributes.delete(k)
|
24
35
|
end
|
25
36
|
end
|
26
|
-
super(attributes)
|
27
37
|
|
28
|
-
|
29
|
-
|
38
|
+
attributes.each do |k, v|
|
39
|
+
_assign_attribute(k, v, force_write_readonly: force_write_readonly)
|
40
|
+
end
|
41
|
+
|
42
|
+
unless nested_parameter_attributes.empty?
|
43
|
+
assign_nested_parameter_attributes(nested_parameter_attributes, force_write_readonly: force_write_readonly)
|
44
|
+
end
|
45
|
+
|
46
|
+
unless multi_parameter_attributes.empty?
|
47
|
+
assign_multiparameter_attributes(multi_parameter_attributes, force_write_readonly: force_write_readonly)
|
48
|
+
end
|
30
49
|
end
|
31
50
|
|
32
51
|
# Assign any deferred nested attributes after the base attributes have been set.
|
33
|
-
def assign_nested_parameter_attributes(pairs)
|
34
|
-
pairs.each { |k, v| _assign_attribute(k, v) }
|
52
|
+
def assign_nested_parameter_attributes(pairs, force_write_readonly: false)
|
53
|
+
pairs.each { |k, v| _assign_attribute(k, v, force_write_readonly: force_write_readonly) }
|
35
54
|
end
|
36
55
|
|
37
56
|
# Instantiates objects for all attribute classes that needs more than one constructor parameter. This is done
|
@@ -40,13 +59,14 @@ module DuckRecord
|
|
40
59
|
# written_on (a date type) with Date.new("2004", "6", "24"). You can also specify a typecast character in the
|
41
60
|
# parentheses to have the parameters typecasted before they're used in the constructor. Use i for Integer and
|
42
61
|
# f for Float. If all the values for a given attribute are empty, the attribute will be set to +nil+.
|
43
|
-
def assign_multiparameter_attributes(pairs)
|
62
|
+
def assign_multiparameter_attributes(pairs, force_write_readonly: false)
|
44
63
|
execute_callstack_for_multiparameter_attributes(
|
45
|
-
extract_callstack_for_multiparameter_attributes(pairs)
|
64
|
+
extract_callstack_for_multiparameter_attributes(pairs),
|
65
|
+
force_write_readonly: force_write_readonly
|
46
66
|
)
|
47
67
|
end
|
48
68
|
|
49
|
-
def execute_callstack_for_multiparameter_attributes(callstack)
|
69
|
+
def execute_callstack_for_multiparameter_attributes(callstack, force_write_readonly: false)
|
50
70
|
errors = []
|
51
71
|
callstack.each do |name, values_with_empty_parameters|
|
52
72
|
begin
|
@@ -55,7 +75,7 @@ module DuckRecord
|
|
55
75
|
else
|
56
76
|
values = values_with_empty_parameters
|
57
77
|
end
|
58
|
-
send("#{name}=", values)
|
78
|
+
send("#{name}=", values, force_write_readonly: force_write_readonly)
|
59
79
|
rescue => ex
|
60
80
|
errors << AttributeAssignmentError.new("error on assignment #{values_with_empty_parameters.values.inspect} to #{name} (#{ex.message})", ex, name)
|
61
81
|
end
|
@@ -87,5 +107,13 @@ module DuckRecord
|
|
87
107
|
def find_parameter_position(multiparameter_name)
|
88
108
|
multiparameter_name.scan(/\(([0-9]*).*\)/).first.first.to_i
|
89
109
|
end
|
110
|
+
|
111
|
+
def _assign_attribute(k, v, force_write_readonly: false)
|
112
|
+
if respond_to?("#{k}=")
|
113
|
+
public_send("#{k}=", v, force_write_readonly: force_write_readonly)
|
114
|
+
else
|
115
|
+
raise UnknownAttributeError.new(self, k)
|
116
|
+
end
|
117
|
+
end
|
90
118
|
end
|
91
119
|
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, force_write_readonly: false)
|
19
19
|
name = ::DuckRecord::AttributeMethods::AttrNames::ATTR_#{safe_name}
|
20
|
-
write_attribute(name, value)
|
20
|
+
write_attribute(name, value, force_write_readonly: force_write_readonly)
|
21
21
|
end
|
22
22
|
alias_method #{(name + '=').inspect}, :__temp__#{safe_name}=
|
23
23
|
undef_method :__temp__#{safe_name}=
|
@@ -28,30 +28,32 @@ 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)
|
31
|
+
def write_attribute(attr_name, value, force_write_readonly: false)
|
32
32
|
name = if self.class.attribute_alias?(attr_name)
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
33
|
+
self.class.attribute_alias(attr_name).to_s
|
34
|
+
else
|
35
|
+
attr_name.to_s
|
36
|
+
end
|
37
37
|
|
38
|
-
write_attribute_with_type_cast(name, value, true)
|
38
|
+
write_attribute_with_type_cast(name, value, true, force_write_readonly: force_write_readonly)
|
39
39
|
end
|
40
40
|
|
41
|
-
def raw_write_attribute(attr_name, value) # :nodoc:
|
42
|
-
write_attribute_with_type_cast(attr_name, value, false)
|
41
|
+
def raw_write_attribute(attr_name, value, force_write_readonly: false) # :nodoc:
|
42
|
+
write_attribute_with_type_cast(attr_name, value, false, force_write_readonly: force_write_readonly)
|
43
43
|
end
|
44
44
|
|
45
45
|
private
|
46
46
|
|
47
47
|
# Handle *= for method_missing.
|
48
|
-
def attribute=(attribute_name, value)
|
49
|
-
write_attribute(attribute_name, value)
|
48
|
+
def attribute=(attribute_name, value, force_write_readonly: false)
|
49
|
+
write_attribute(attribute_name, value, force_write_readonly: force_write_readonly)
|
50
50
|
end
|
51
51
|
|
52
|
-
def write_attribute_with_type_cast(attr_name, value, should_type_cast)
|
52
|
+
def write_attribute_with_type_cast(attr_name, value, should_type_cast, force_write_readonly: false)
|
53
53
|
attr_name = attr_name.to_s
|
54
54
|
|
55
|
+
return if !force_write_readonly && self.class.readonly_attributes.include?(attr_name)
|
56
|
+
|
55
57
|
if should_type_cast
|
56
58
|
@attributes.write_from_user(attr_name, value)
|
57
59
|
else
|
data/lib/duck_record/base.rb
CHANGED
data/lib/duck_record/core.rb
CHANGED
@@ -0,0 +1,23 @@
|
|
1
|
+
module DuckRecord
|
2
|
+
module ReadonlyAttributes
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
class_attribute :_attr_readonly, instance_accessor: false
|
7
|
+
self._attr_readonly = []
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
# Attributes listed as readonly will be used to create a new record but update operations will
|
12
|
+
# ignore these fields.
|
13
|
+
def attr_readonly(*attributes)
|
14
|
+
self._attr_readonly = Set.new(attributes.map(&:to_s)) + (_attr_readonly || [])
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns an array of all the attributes that have been specified as readonly.
|
18
|
+
def readonly_attributes
|
19
|
+
_attr_readonly
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/duck_record/version.rb
CHANGED
data/lib/duck_record.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.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- jasl
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-03-
|
11
|
+
date: 2017-03-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -100,6 +100,7 @@ files:
|
|
100
100
|
- lib/duck_record/model_schema.rb
|
101
101
|
- lib/duck_record/nested_attributes.rb
|
102
102
|
- lib/duck_record/nested_validate_association.rb
|
103
|
+
- lib/duck_record/readonly_attributes.rb
|
103
104
|
- lib/duck_record/reflection.rb
|
104
105
|
- lib/duck_record/serialization.rb
|
105
106
|
- lib/duck_record/translation.rb
|