active_data 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.codeclimate.yml +13 -0
- data/.rubocop.yml +56 -0
- data/.rubocop_todo.yml +53 -0
- data/.rvmrc +1 -1
- data/.travis.yml +15 -2
- data/Appraisals +1 -1
- data/CHANGELOG.md +31 -0
- data/Guardfile +8 -8
- data/README.md +256 -0
- data/Rakefile +2 -4
- data/active_data.gemspec +8 -7
- data/gemfiles/rails.4.0.gemfile +1 -1
- data/gemfiles/rails.4.1.gemfile +1 -1
- data/gemfiles/rails.4.2.gemfile +1 -1
- data/gemfiles/rails.5.0.gemfile +1 -1
- data/gemfiles/rails.5.1.gemfile +14 -0
- data/lib/active_data/active_record/associations.rb +18 -13
- data/lib/active_data/active_record/nested_attributes.rb +8 -14
- data/lib/active_data/base.rb +13 -0
- data/lib/active_data/config.rb +4 -4
- data/lib/active_data/errors.rb +29 -13
- data/lib/active_data/extensions.rb +22 -21
- data/lib/active_data/model/associations/base.rb +22 -6
- data/lib/active_data/model/associations/embeds_any.rb +17 -0
- data/lib/active_data/model/associations/embeds_many.rb +29 -19
- data/lib/active_data/model/associations/embeds_one.rb +30 -26
- data/lib/active_data/model/associations/nested_attributes.rb +82 -50
- data/lib/active_data/model/associations/persistence_adapters/active_record/referenced_proxy.rb +31 -0
- data/lib/active_data/model/associations/persistence_adapters/active_record.rb +66 -0
- data/lib/active_data/model/associations/persistence_adapters/base.rb +53 -0
- data/lib/active_data/model/associations/references_any.rb +41 -0
- data/lib/active_data/model/associations/references_many.rb +51 -37
- data/lib/active_data/model/associations/references_one.rb +43 -41
- data/lib/active_data/model/associations/reflections/base.rb +19 -29
- data/lib/active_data/model/associations/reflections/embeds_any.rb +43 -0
- data/lib/active_data/model/associations/reflections/embeds_many.rb +3 -13
- data/lib/active_data/model/associations/reflections/embeds_one.rb +5 -37
- data/lib/active_data/model/associations/reflections/references_any.rb +62 -0
- data/lib/active_data/model/associations/reflections/references_many.rb +7 -7
- data/lib/active_data/model/associations/reflections/references_one.rb +9 -7
- data/lib/active_data/model/associations/reflections/singular.rb +35 -0
- data/lib/active_data/model/associations/validations.rb +2 -27
- data/lib/active_data/model/associations.rb +12 -10
- data/lib/active_data/model/attributes/attribute.rb +10 -10
- data/lib/active_data/model/attributes/base.rb +8 -7
- data/lib/active_data/model/attributes/localized.rb +4 -4
- data/lib/active_data/model/attributes/reference_many.rb +6 -8
- data/lib/active_data/model/attributes/reference_one.rb +17 -9
- data/lib/active_data/model/attributes/reflections/attribute.rb +2 -2
- data/lib/active_data/model/attributes/reflections/base.rb +8 -11
- data/lib/active_data/model/attributes/reflections/localized.rb +2 -2
- data/lib/active_data/model/attributes/reflections/reference_one.rb +11 -22
- data/lib/active_data/model/attributes/reflections/represents.rb +5 -6
- data/lib/active_data/model/attributes/represents.rb +6 -5
- data/lib/active_data/model/attributes.rb +33 -87
- data/lib/active_data/model/callbacks.rb +6 -7
- data/lib/active_data/model/conventions.rb +2 -0
- data/lib/active_data/model/dirty.rb +4 -4
- data/lib/active_data/model/lifecycle.rb +18 -20
- data/lib/active_data/model/localization.rb +5 -2
- data/lib/active_data/model/persistence.rb +2 -2
- data/lib/active_data/model/primary.rb +19 -14
- data/lib/active_data/model/representation.rb +81 -0
- data/lib/active_data/model/scopes.rb +22 -12
- data/lib/active_data/model/validations/associated.rb +3 -2
- data/lib/active_data/model/validations/nested.rb +6 -1
- data/lib/active_data/model/validations.rb +3 -3
- data/lib/active_data/model.rb +2 -1
- data/lib/active_data/undefined_class.rb +9 -0
- data/lib/active_data/version.rb +1 -1
- data/lib/active_data.rb +40 -17
- data/spec/lib/active_data/active_record/associations_spec.rb +107 -45
- data/spec/lib/active_data/active_record/nested_attributes_spec.rb +1 -2
- data/spec/lib/active_data/config_spec.rb +37 -15
- data/spec/lib/active_data/model/associations/embeds_many_spec.rb +475 -172
- data/spec/lib/active_data/model/associations/embeds_one_spec.rb +353 -96
- data/spec/lib/active_data/model/associations/nested_attributes_spec.rb +108 -12
- data/spec/lib/active_data/model/associations/persistence_adapters/active_record_spec.rb +58 -0
- data/spec/lib/active_data/model/associations/references_many_spec.rb +440 -64
- data/spec/lib/active_data/model/associations/references_one_spec.rb +347 -36
- data/spec/lib/active_data/model/associations/reflections/embeds_many_spec.rb +8 -7
- data/spec/lib/active_data/model/associations/reflections/embeds_one_spec.rb +7 -6
- data/spec/lib/active_data/model/associations/reflections/references_many_spec.rb +81 -33
- data/spec/lib/active_data/model/associations/reflections/references_one_spec.rb +116 -37
- data/spec/lib/active_data/model/associations/validations_spec.rb +27 -43
- data/spec/lib/active_data/model/associations_spec.rb +34 -25
- data/spec/lib/active_data/model/attributes/attribute_spec.rb +26 -23
- data/spec/lib/active_data/model/attributes/base_spec.rb +5 -6
- data/spec/lib/active_data/model/attributes/collection_spec.rb +7 -8
- data/spec/lib/active_data/model/attributes/dictionary_spec.rb +40 -33
- data/spec/lib/active_data/model/attributes/localized_spec.rb +27 -28
- data/spec/lib/active_data/model/attributes/reflections/attribute_spec.rb +6 -6
- data/spec/lib/active_data/model/attributes/represents_spec.rb +10 -78
- data/spec/lib/active_data/model/attributes_spec.rb +150 -45
- data/spec/lib/active_data/model/callbacks_spec.rb +69 -70
- data/spec/lib/active_data/model/conventions_spec.rb +0 -1
- data/spec/lib/active_data/model/dirty_spec.rb +22 -13
- data/spec/lib/active_data/model/lifecycle_spec.rb +49 -23
- data/spec/lib/active_data/model/persistence_spec.rb +5 -6
- data/spec/lib/active_data/model/representation_spec.rb +126 -0
- data/spec/lib/active_data/model/scopes_spec.rb +1 -3
- data/spec/lib/active_data/model/typecasting_spec.rb +6 -5
- data/spec/lib/active_data/model/validations/associated_spec.rb +26 -18
- data/spec/lib/active_data/model/validations/nested_spec.rb +89 -18
- data/spec/lib/active_data/model_spec.rb +1 -2
- data/spec/lib/active_data_spec.rb +0 -1
- data/spec/shared/nested_attribute_examples.rb +332 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/support/model_helpers.rb +2 -2
- data/spec/support/muffle_helper.rb +7 -0
- metadata +52 -18
- data/lib/active_data/model/associations/collection/referenced.rb +0 -26
- data/lib/active_data/model/associations/reflections/reference_reflection.rb +0 -45
- data/spec/lib/active_data/model/nested_attributes.rb +0 -202
@@ -2,13 +2,13 @@ module ActiveData
|
|
2
2
|
module Model
|
3
3
|
module Attributes
|
4
4
|
class ReferenceOne < Base
|
5
|
-
def write
|
5
|
+
def write(value)
|
6
6
|
pollute do
|
7
7
|
previous = type_casted_value
|
8
8
|
result = write_value value
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
changed = (!value.nil? && type_casted_value.nil?) || type_casted_value != previous
|
10
|
+
|
11
|
+
association.reset if changed
|
12
12
|
result
|
13
13
|
end
|
14
14
|
end
|
@@ -21,18 +21,26 @@ module ActiveData
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
+
def type_casted_value
|
25
|
+
variable_cache(:value) do
|
26
|
+
typecast(read_before_type_cast)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
24
30
|
def read_before_type_cast
|
25
31
|
@value_cache
|
26
32
|
end
|
27
33
|
|
28
|
-
|
34
|
+
def type
|
35
|
+
@type ||= association.reflection.persistence_adapter.primary_key_type
|
36
|
+
end
|
29
37
|
|
30
|
-
def
|
31
|
-
|
32
|
-
typecast(read_before_type_cast)
|
33
|
-
end
|
38
|
+
def typecaster
|
39
|
+
@typecaster ||= ActiveData.typecaster(type.ancestors.grep(Class))
|
34
40
|
end
|
35
41
|
|
42
|
+
private
|
43
|
+
|
36
44
|
def association
|
37
45
|
@association ||= owner.association(reflection.association)
|
38
46
|
end
|
@@ -3,13 +3,13 @@ module ActiveData
|
|
3
3
|
module Attributes
|
4
4
|
module Reflections
|
5
5
|
class Attribute < Base
|
6
|
-
def self.build
|
6
|
+
def self.build(target, generated_methods, name, *args, &block)
|
7
7
|
attribute = super(target, generated_methods, name, *args, &block)
|
8
8
|
generate_methods name, generated_methods
|
9
9
|
attribute
|
10
10
|
end
|
11
11
|
|
12
|
-
def self.generate_methods
|
12
|
+
def self.generate_methods(name, target)
|
13
13
|
target.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
14
14
|
def #{name}
|
15
15
|
attribute('#{name}').read
|
@@ -5,37 +5,34 @@ module ActiveData
|
|
5
5
|
class Base
|
6
6
|
attr_reader :name, :options
|
7
7
|
class << self
|
8
|
-
def build
|
8
|
+
def build(_target, _generated_methods, name, *args, &block)
|
9
9
|
options = args.extract_options!
|
10
|
-
options
|
11
|
-
options
|
10
|
+
options[:type] = args.first if args.first
|
11
|
+
options[:default] = block if block
|
12
12
|
new(name, options)
|
13
13
|
end
|
14
14
|
|
15
|
-
def generate_methods
|
16
|
-
end
|
15
|
+
def generate_methods(name, target) end
|
17
16
|
|
18
17
|
def attribute_class
|
19
18
|
@attribute_class ||= "ActiveData::Model::Attributes::#{name.demodulize}".constantize
|
20
19
|
end
|
21
20
|
end
|
22
21
|
|
23
|
-
def initialize
|
22
|
+
def initialize(name, options = {})
|
24
23
|
@name = name.to_s
|
25
24
|
@options = options
|
26
25
|
end
|
27
26
|
|
28
|
-
def build_attribute
|
27
|
+
def build_attribute(owner, raw_value = ActiveData::UNDEFINED)
|
29
28
|
attribute = self.class.attribute_class.new(name, owner)
|
30
|
-
attribute.write_value(raw_value)
|
29
|
+
attribute.write_value(raw_value) unless raw_value == ActiveData::UNDEFINED
|
31
30
|
attribute
|
32
31
|
end
|
33
32
|
|
34
33
|
def type
|
35
34
|
@type ||= case options[:type]
|
36
|
-
when
|
37
|
-
options[:type].call
|
38
|
-
when Class
|
35
|
+
when Class, Module
|
39
36
|
options[:type]
|
40
37
|
when nil
|
41
38
|
raise "Type is not specified for `#{name}`"
|
@@ -3,13 +3,13 @@ module ActiveData
|
|
3
3
|
module Attributes
|
4
4
|
module Reflections
|
5
5
|
class Localized < Attribute
|
6
|
-
def self.build
|
6
|
+
def self.build(target, generated_methods, name, *args, &block)
|
7
7
|
attribute = super(target, generated_methods, name, *args, &block)
|
8
8
|
generate_methods name, generated_methods
|
9
9
|
attribute
|
10
10
|
end
|
11
11
|
|
12
|
-
def self.generate_methods
|
12
|
+
def self.generate_methods(name, target)
|
13
13
|
target.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
14
14
|
def #{name}_translations
|
15
15
|
attribute('#{name}').read
|
@@ -3,32 +3,13 @@ module ActiveData
|
|
3
3
|
module Attributes
|
4
4
|
module Reflections
|
5
5
|
class ReferenceOne < Base
|
6
|
-
|
7
|
-
integer: Integer,
|
8
|
-
float: Float,
|
9
|
-
decimal: BigDecimal,
|
10
|
-
datetime: Time,
|
11
|
-
timestamp: Time,
|
12
|
-
time: Time,
|
13
|
-
date: Date,
|
14
|
-
text: String,
|
15
|
-
string: String,
|
16
|
-
binary: String,
|
17
|
-
boolean: Boolean
|
18
|
-
}
|
19
|
-
|
20
|
-
def self.build target, generated_methods, name, *args, &block
|
6
|
+
def self.build(_target, generated_methods, name, *args)
|
21
7
|
options = args.extract_options!
|
22
8
|
generate_methods name, generated_methods
|
23
|
-
|
24
|
-
reflection = target.reflect_on_association(options[:association])
|
25
|
-
column = reflection.klass.columns_hash[reflection.primary_key.to_s]
|
26
|
-
TYPES[column.type]
|
27
|
-
}
|
28
|
-
new(name, options.reverse_merge(type: type_proc))
|
9
|
+
new(name, options)
|
29
10
|
end
|
30
11
|
|
31
|
-
def self.generate_methods
|
12
|
+
def self.generate_methods(name, target)
|
32
13
|
target.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
33
14
|
def #{name}
|
34
15
|
attribute('#{name}').read
|
@@ -48,6 +29,14 @@ module ActiveData
|
|
48
29
|
RUBY
|
49
30
|
end
|
50
31
|
|
32
|
+
def type
|
33
|
+
Object
|
34
|
+
end
|
35
|
+
|
36
|
+
def inspect_reflection
|
37
|
+
"#{name}: (reference)"
|
38
|
+
end
|
39
|
+
|
51
40
|
def association
|
52
41
|
@association ||= options[:association].to_s
|
53
42
|
end
|
@@ -3,20 +3,19 @@ module ActiveData
|
|
3
3
|
module Attributes
|
4
4
|
module Reflections
|
5
5
|
class Represents < Attribute
|
6
|
-
def self.build
|
6
|
+
def self.build(target, generated_methods, name, *args, &block)
|
7
7
|
options = args.extract_options!
|
8
8
|
|
9
9
|
reference = target.reflect_on_association(options[:of]) if target.respond_to?(:reflect_on_association)
|
10
10
|
reference ||= target.reflect_on_attribute(options[:of]) if target.respond_to?(:reflect_on_attribute)
|
11
|
-
if reference
|
12
|
-
|
13
|
-
|
14
|
-
end
|
11
|
+
options[:of] = reference.name if reference
|
12
|
+
validates_nested = target.respond_to?(:validates_nested) && !target.validates_nested?(options[:of])
|
13
|
+
target.validates_nested(options[:of]) if validates_nested
|
15
14
|
|
16
15
|
super(target, generated_methods, name, *args, options, &block)
|
17
16
|
end
|
18
17
|
|
19
|
-
def initialize
|
18
|
+
def initialize(name, options)
|
20
19
|
super
|
21
20
|
raise ArgumentError, "Undefined reference for `#{name}`" if reference.blank?
|
22
21
|
end
|
@@ -4,7 +4,7 @@ module ActiveData
|
|
4
4
|
class Represents < Attribute
|
5
5
|
delegate :reader, :reader_before_type_cast, :writer, to: :reflection
|
6
6
|
|
7
|
-
def write
|
7
|
+
def write(value)
|
8
8
|
return if readonly?
|
9
9
|
pollute do
|
10
10
|
reset
|
@@ -48,10 +48,11 @@ module ActiveData
|
|
48
48
|
|
49
49
|
def read_value_before_type_cast
|
50
50
|
ref = reference
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
51
|
+
return unless ref
|
52
|
+
if ref.respond_to?(reader_before_type_cast)
|
53
|
+
ref.public_send(reader_before_type_cast)
|
54
|
+
else
|
55
|
+
ref.public_send(reader)
|
55
56
|
end
|
56
57
|
end
|
57
58
|
|
@@ -1,20 +1,12 @@
|
|
1
1
|
require 'active_data/model/attributes/reflections/base'
|
2
|
-
require 'active_data/model/attributes/reflections/reference_one'
|
3
|
-
require 'active_data/model/attributes/reflections/reference_many'
|
4
2
|
require 'active_data/model/attributes/reflections/attribute'
|
5
3
|
require 'active_data/model/attributes/reflections/collection'
|
6
4
|
require 'active_data/model/attributes/reflections/dictionary'
|
7
|
-
require 'active_data/model/attributes/reflections/localized'
|
8
|
-
require 'active_data/model/attributes/reflections/represents'
|
9
5
|
|
10
6
|
require 'active_data/model/attributes/base'
|
11
|
-
require 'active_data/model/attributes/reference_one'
|
12
|
-
require 'active_data/model/attributes/reference_many'
|
13
7
|
require 'active_data/model/attributes/attribute'
|
14
8
|
require 'active_data/model/attributes/collection'
|
15
9
|
require 'active_data/model/attributes/dictionary'
|
16
|
-
require 'active_data/model/attributes/localized'
|
17
|
-
require 'active_data/model/attributes/represents'
|
18
10
|
|
19
11
|
module ActiveData
|
20
12
|
module Model
|
@@ -37,31 +29,21 @@ module ActiveData
|
|
37
29
|
end
|
38
30
|
|
39
31
|
module ClassMethods
|
40
|
-
def represents(*names, &block)
|
41
|
-
options = names.extract_options!
|
42
|
-
names.each do |name|
|
43
|
-
add_attribute(Reflections::Represents, name, options, &block)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
32
|
def add_attribute(reflection_class, *args, &block)
|
48
33
|
reflection = reflection_class.build(self, generated_attributes_methods, *args, &block)
|
49
34
|
self._attributes = _attributes.merge(reflection.name => reflection)
|
50
|
-
|
51
|
-
|
52
|
-
end
|
35
|
+
should_define_dirty = (dirty? && reflection_class != ActiveData::Model::Attributes::Reflections::Base)
|
36
|
+
define_dirty(reflection.name, generated_attributes_methods) if should_define_dirty
|
53
37
|
reflection
|
54
38
|
end
|
55
39
|
|
56
40
|
def alias_attribute(alias_name, attribute_name)
|
57
41
|
reflection = reflect_on_attribute(attribute_name)
|
58
|
-
raise ArgumentError
|
59
|
-
raise ArgumentError
|
42
|
+
raise ArgumentError, "Unable to alias undefined attribute `#{attribute_name}` on #{self}" unless reflection
|
43
|
+
raise ArgumentError, "Unable to alias base attribute `#{attribute_name}`" if reflection.class == ActiveData::Model::Attributes::Reflections::Base
|
60
44
|
reflection.class.generate_methods alias_name, generated_attributes_methods
|
61
45
|
self._attribute_aliases = _attribute_aliases.merge(alias_name.to_s => reflection.name)
|
62
|
-
if dirty?
|
63
|
-
define_dirty alias_name, generated_attributes_methods
|
64
|
-
end
|
46
|
+
define_dirty alias_name, generated_attributes_methods if dirty?
|
65
47
|
reflection
|
66
48
|
end
|
67
49
|
|
@@ -70,7 +52,7 @@ module ActiveData
|
|
70
52
|
_attributes[_attribute_aliases[name] || name]
|
71
53
|
end
|
72
54
|
|
73
|
-
def has_attribute?
|
55
|
+
def has_attribute?(name) # rubocop:disable Naming/PredicateName
|
74
56
|
name = name.to_s
|
75
57
|
_attributes.key?(_attribute_aliases[name] || name)
|
76
58
|
end
|
@@ -89,24 +71,13 @@ module ActiveData
|
|
89
71
|
"#{original_inspect}(#{attributes_for_inspect.presence || 'no attributes'})"
|
90
72
|
end
|
91
73
|
|
92
|
-
def represented_attributes
|
93
|
-
@represented_attributes ||= _attributes.values.select do |attribute|
|
94
|
-
attribute.is_a? ActiveData::Model::Attributes::Reflections::Represents
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
def represented_names_and_aliases
|
99
|
-
@represented_names_and_aliases ||= represented_attributes.flat_map do |attribute|
|
100
|
-
[attribute.name, *inverted_attribute_aliases[attribute.name]]
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
74
|
def dirty?
|
105
75
|
false
|
106
76
|
end
|
107
77
|
|
108
78
|
def with_sanitize(value)
|
109
|
-
previous_sanitize
|
79
|
+
previous_sanitize = _sanitize
|
80
|
+
self._sanitize = value
|
110
81
|
yield
|
111
82
|
ensure
|
112
83
|
self._sanitize = previous_sanitize
|
@@ -120,7 +91,7 @@ module ActiveData
|
|
120
91
|
|
121
92
|
def attributes_for_inspect
|
122
93
|
attribute_names(false).map do |name|
|
123
|
-
prefix = respond_to?(:_primary_name) && _primary_name == name ?
|
94
|
+
prefix = respond_to?(:_primary_name) && _primary_name == name ? '*' : ''
|
124
95
|
"#{prefix}#{_attributes[name].inspect_reflection}"
|
125
96
|
end.join(', ')
|
126
97
|
end
|
@@ -128,7 +99,7 @@ module ActiveData
|
|
128
99
|
def generated_attributes_methods
|
129
100
|
@generated_attributes_methods ||=
|
130
101
|
const_set(:GeneratedAttributesMethods, Module.new)
|
131
|
-
|
102
|
+
.tap { |proxy| include proxy }
|
132
103
|
end
|
133
104
|
|
134
105
|
def inverted_attribute_aliases
|
@@ -139,37 +110,38 @@ module ActiveData
|
|
139
110
|
end
|
140
111
|
end
|
141
112
|
|
142
|
-
def initialize
|
113
|
+
def initialize(attrs = {})
|
143
114
|
assign_attributes attrs
|
144
115
|
end
|
145
116
|
|
146
|
-
def ==
|
117
|
+
def ==(other)
|
147
118
|
super || other.instance_of?(self.class) && other.attributes(false) == attributes(false)
|
148
119
|
end
|
149
120
|
alias_method :eql?, :==
|
150
121
|
|
151
122
|
def attribute(name)
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
123
|
+
reflection = self.class.reflect_on_attribute(name)
|
124
|
+
return unless reflection
|
125
|
+
initial_value = @initial_attributes.to_h.fetch(reflection.name, ActiveData::UNDEFINED)
|
126
|
+
@_attributes ||= {}
|
127
|
+
@_attributes[reflection.name] ||= reflection.build_attribute(self, initial_value)
|
156
128
|
end
|
157
129
|
|
158
|
-
def write_attribute
|
130
|
+
def write_attribute(name, value)
|
159
131
|
attribute(name).write(value)
|
160
132
|
end
|
161
133
|
alias_method :[]=, :write_attribute
|
162
134
|
|
163
|
-
def read_attribute
|
135
|
+
def read_attribute(name)
|
164
136
|
attribute(name).read
|
165
137
|
end
|
166
138
|
alias_method :[], :read_attribute
|
167
139
|
|
168
|
-
def read_attribute_before_type_cast
|
140
|
+
def read_attribute_before_type_cast(name)
|
169
141
|
attribute(name).read_before_type_cast
|
170
142
|
end
|
171
143
|
|
172
|
-
def attribute_present?
|
144
|
+
def attribute_present?(name)
|
173
145
|
attribute(name).value_present?
|
174
146
|
end
|
175
147
|
|
@@ -177,35 +149,22 @@ module ActiveData
|
|
177
149
|
Hash[attribute_names(include_associations).map { |name| [name, read_attribute(name)] }]
|
178
150
|
end
|
179
151
|
|
180
|
-
def update
|
152
|
+
def update(attrs)
|
181
153
|
assign_attributes(attrs)
|
182
154
|
end
|
183
155
|
alias_method :update_attributes, :update
|
184
156
|
|
185
|
-
def assign_attributes
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
attrs.stringify_keys!
|
190
|
-
represented_attrs = self.class.represented_names_and_aliases
|
191
|
-
.each_with_object({}) do |name, result|
|
192
|
-
result[name] = attrs.delete(name) if attrs.has_key?(name)
|
193
|
-
end
|
194
|
-
if self.class.is_a?(ActiveData::Model::Associations::NestedAttributes)
|
195
|
-
nested_attrs = self.class.nested_attributes_options.keys
|
196
|
-
.each_with_object({}) do |association_name, result|
|
197
|
-
name = "#{association_name}_attributes"
|
198
|
-
result[name] = attrs.delete(name) if attrs.has_key?(name)
|
199
|
-
end
|
200
|
-
end
|
157
|
+
def assign_attributes(attrs)
|
158
|
+
attrs.each do |name, value|
|
159
|
+
name = name.to_s
|
160
|
+
sanitize_value = self.class._sanitize && name == self.class.primary_name
|
201
161
|
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
162
|
+
if respond_to?("#{name}=") && !sanitize_value
|
163
|
+
public_send("#{name}=", value)
|
164
|
+
else
|
165
|
+
logger.info("Ignoring #{sanitize_value ? 'primary' : 'undefined'} `#{name}` attribute value for #{self} during mass-assignment")
|
166
|
+
end
|
207
167
|
end
|
208
|
-
true
|
209
168
|
end
|
210
169
|
alias_method :attributes=, :assign_attributes
|
211
170
|
|
@@ -213,7 +172,7 @@ module ActiveData
|
|
213
172
|
"#<#{self.class.send(:original_inspect)} #{attributes_for_inspect.presence || '(no attributes)'}>"
|
214
173
|
end
|
215
174
|
|
216
|
-
def initialize_copy
|
175
|
+
def initialize_copy(_)
|
217
176
|
@initial_attributes = Hash[attribute_names.map do |name|
|
218
177
|
[name, read_attribute_before_type_cast(name)]
|
219
178
|
end]
|
@@ -223,22 +182,9 @@ module ActiveData
|
|
223
182
|
|
224
183
|
private
|
225
184
|
|
226
|
-
def _assign_attributes attrs
|
227
|
-
attrs.each do |name, value|
|
228
|
-
name = name.to_s
|
229
|
-
sanitize_value = self.class._sanitize && name == self.class.primary_name
|
230
|
-
|
231
|
-
if respond_to?("#{name}=") && !sanitize_value
|
232
|
-
public_send("#{name}=", value)
|
233
|
-
else
|
234
|
-
logger.info("Ignoring #{sanitize_value ? 'primary' : 'undefined'} `#{name}` attribute value for #{self} during mass-assignment")
|
235
|
-
end
|
236
|
-
end
|
237
|
-
end
|
238
|
-
|
239
185
|
def attributes_for_inspect
|
240
186
|
attribute_names(false).map do |name|
|
241
|
-
prefix = self.class.primary_name == name ?
|
187
|
+
prefix = self.class.primary_name == name ? '*' : ''
|
242
188
|
"#{prefix}#{attribute(name).inspect_attribute}"
|
243
189
|
end.join(', ')
|
244
190
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
module ActiveData
|
2
2
|
module Model
|
3
|
-
|
4
3
|
# == Callbacks for ActiveData::Model lifecycle
|
5
4
|
#
|
6
5
|
# Provides ActiveModel callbacks support for lifecycle
|
@@ -45,24 +44,24 @@ module ActiveData
|
|
45
44
|
end
|
46
45
|
|
47
46
|
module PrependMethods
|
48
|
-
def initialize
|
49
|
-
super
|
47
|
+
def initialize(*_)
|
48
|
+
super
|
50
49
|
run_callbacks :initialize
|
51
50
|
end
|
52
51
|
|
53
|
-
def save_object
|
52
|
+
def save_object(&block)
|
54
53
|
run_callbacks(:save) { super(&block) }
|
55
54
|
end
|
56
55
|
|
57
|
-
def create_object
|
56
|
+
def create_object(&block)
|
58
57
|
run_callbacks(:create) { super(&block) }
|
59
58
|
end
|
60
59
|
|
61
|
-
def update_object
|
60
|
+
def update_object(&block)
|
62
61
|
run_callbacks(:update) { super(&block) }
|
63
62
|
end
|
64
63
|
|
65
|
-
def destroy_object
|
64
|
+
def destroy_object(&block)
|
66
65
|
run_callbacks(:destroy) { super(&block) }
|
67
66
|
end
|
68
67
|
end
|
@@ -12,8 +12,8 @@ module ActiveData
|
|
12
12
|
def self.append_features(base)
|
13
13
|
unconcerned_append_features(base)
|
14
14
|
end
|
15
|
-
|
16
|
-
end
|
15
|
+
|
16
|
+
def self.included(_base); end
|
17
17
|
end
|
18
18
|
|
19
19
|
included do
|
@@ -42,13 +42,13 @@ module ActiveData
|
|
42
42
|
attribute_names(false).each do |name|
|
43
43
|
define_dirty name, generated_attributes_methods
|
44
44
|
end
|
45
|
-
_attribute_aliases.
|
45
|
+
_attribute_aliases.each_key do |name|
|
46
46
|
define_dirty name, generated_attributes_methods
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
50
|
module ClassMethods
|
51
|
-
def define_dirty
|
51
|
+
def define_dirty(method, target = self)
|
52
52
|
reflection = reflect_on_attribute(method)
|
53
53
|
name = reflection ? reflection.name : method
|
54
54
|
|