activemodel 5.2.0.rc1 → 5.2.0.rc2
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/CHANGELOG.md +7 -0
- data/README.rdoc +1 -1
- data/lib/active_model/attribute_assignment.rb +2 -0
- data/lib/active_model/attribute_mutation_tracker.rb +3 -4
- data/lib/active_model/attribute_set/builder.rb +11 -9
- data/lib/active_model/attributes.rb +4 -0
- data/lib/active_model/dirty.rb +69 -39
- data/lib/active_model/gem_version.rb +1 -1
- data/lib/active_model/serialization.rb +1 -1
- data/lib/active_model/type/date.rb +1 -1
- data/lib/active_model/type/time.rb +2 -6
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 97b6d1fb9b61ef956d88c6ee764394e9ccc0fcad2333073a876066fd9c7fcb7a
|
4
|
+
data.tar.gz: 86e60a71d98b585c900c3351a4c4fcf1f16ac73e4c0fc0b4595a443733c31f50
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3d11a69342faac6bed87647ec40059830c8441459f30a6c9d94f3656ff2ce89a08fe3b12eed6846bae3352eb5fb929d4e30ab91611e569e7dae5f9e851fe47ba
|
7
|
+
data.tar.gz: 3493c445e4a3db83fcad5b043a82d16cf1242286bd49e73755bebf82a17f6b0f8f78d9563d2eac7d6ba739dc921b8a9a8a9ce2108098e4aab72bfa335658feec
|
data/CHANGELOG.md
CHANGED
data/README.rdoc
CHANGED
@@ -239,7 +239,7 @@ The latest version of Active Model can be installed with RubyGems:
|
|
239
239
|
|
240
240
|
Source code can be downloaded as part of the Rails project on GitHub
|
241
241
|
|
242
|
-
* https://github.com/rails/rails/tree/
|
242
|
+
* https://github.com/rails/rails/tree/5-2-stable/activemodel
|
243
243
|
|
244
244
|
|
245
245
|
== License
|
@@ -35,10 +35,6 @@ module ActiveModel
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
-
def changed_attribute_names
|
39
|
-
attr_names.select { |attr| changed?(attr) }
|
40
|
-
end
|
41
|
-
|
42
38
|
def any_changes?
|
43
39
|
attr_names.any? { |attr| changed?(attr) }
|
44
40
|
end
|
@@ -113,5 +109,8 @@ module ActiveModel
|
|
113
109
|
|
114
110
|
def original_value(*)
|
115
111
|
end
|
112
|
+
|
113
|
+
def force_change(*)
|
114
|
+
end
|
116
115
|
end
|
117
116
|
end
|
@@ -22,12 +22,12 @@ module ActiveModel
|
|
22
22
|
class LazyAttributeHash # :nodoc:
|
23
23
|
delegate :transform_values, :each_key, :each_value, :fetch, :except, to: :materialize
|
24
24
|
|
25
|
-
def initialize(types, values, additional_types, default_attributes)
|
25
|
+
def initialize(types, values, additional_types, default_attributes, delegate_hash = {})
|
26
26
|
@types = types
|
27
27
|
@values = values
|
28
28
|
@additional_types = additional_types
|
29
29
|
@materialized = false
|
30
|
-
@delegate_hash =
|
30
|
+
@delegate_hash = delegate_hash
|
31
31
|
@default_attributes = default_attributes
|
32
32
|
end
|
33
33
|
|
@@ -76,15 +76,17 @@ module ActiveModel
|
|
76
76
|
end
|
77
77
|
|
78
78
|
def marshal_dump
|
79
|
-
|
79
|
+
[@types, @values, @additional_types, @default_attributes, @delegate_hash]
|
80
80
|
end
|
81
81
|
|
82
|
-
def marshal_load(
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
82
|
+
def marshal_load(values)
|
83
|
+
if values.is_a?(Hash)
|
84
|
+
empty_hash = {}.freeze
|
85
|
+
initialize(empty_hash, empty_hash, empty_hash, empty_hash, values)
|
86
|
+
@materialized = true
|
87
|
+
else
|
88
|
+
initialize(*values)
|
89
|
+
end
|
88
90
|
end
|
89
91
|
|
90
92
|
protected
|
data/lib/active_model/dirty.rb
CHANGED
@@ -3,7 +3,6 @@
|
|
3
3
|
require "active_support/hash_with_indifferent_access"
|
4
4
|
require "active_support/core_ext/object/duplicable"
|
5
5
|
require "active_model/attribute_mutation_tracker"
|
6
|
-
require "active_model/attribute_set"
|
7
6
|
|
8
7
|
module ActiveModel
|
9
8
|
# == Active \Model \Dirty
|
@@ -143,8 +142,11 @@ module ActiveModel
|
|
143
142
|
end
|
144
143
|
|
145
144
|
def changes_applied # :nodoc:
|
146
|
-
|
145
|
+
unless defined?(@attributes)
|
146
|
+
@previously_changed = changes
|
147
|
+
end
|
147
148
|
@mutations_before_last_save = mutations_from_database
|
149
|
+
@attributes_changed_by_setter = ActiveSupport::HashWithIndifferentAccess.new
|
148
150
|
forget_attribute_assignments
|
149
151
|
@mutations_from_database = nil
|
150
152
|
end
|
@@ -155,7 +157,7 @@ module ActiveModel
|
|
155
157
|
# person.name = 'bob'
|
156
158
|
# person.changed? # => true
|
157
159
|
def changed?
|
158
|
-
|
160
|
+
changed_attributes.present?
|
159
161
|
end
|
160
162
|
|
161
163
|
# Returns an array with the name of the attributes with unsaved changes.
|
@@ -164,24 +166,24 @@ module ActiveModel
|
|
164
166
|
# person.name = 'bob'
|
165
167
|
# person.changed # => ["name"]
|
166
168
|
def changed
|
167
|
-
|
169
|
+
changed_attributes.keys
|
168
170
|
end
|
169
171
|
|
170
172
|
# Handles <tt>*_changed?</tt> for +method_missing+.
|
171
173
|
def attribute_changed?(attr, from: OPTION_NOT_GIVEN, to: OPTION_NOT_GIVEN) # :nodoc:
|
172
|
-
!!
|
174
|
+
!!changes_include?(attr) &&
|
173
175
|
(to == OPTION_NOT_GIVEN || to == _read_attribute(attr)) &&
|
174
|
-
(from == OPTION_NOT_GIVEN || from ==
|
176
|
+
(from == OPTION_NOT_GIVEN || from == changed_attributes[attr])
|
175
177
|
end
|
176
178
|
|
177
179
|
# Handles <tt>*_was</tt> for +method_missing+.
|
178
180
|
def attribute_was(attr) # :nodoc:
|
179
|
-
|
181
|
+
attribute_changed?(attr) ? changed_attributes[attr] : _read_attribute(attr)
|
180
182
|
end
|
181
183
|
|
182
184
|
# Handles <tt>*_previously_changed?</tt> for +method_missing+.
|
183
185
|
def attribute_previously_changed?(attr) #:nodoc:
|
184
|
-
|
186
|
+
previous_changes_include?(attr)
|
185
187
|
end
|
186
188
|
|
187
189
|
# Restore all previous data of the provided attributes.
|
@@ -191,12 +193,15 @@ module ActiveModel
|
|
191
193
|
|
192
194
|
# Clears all dirty data: current changes and previous changes.
|
193
195
|
def clear_changes_information
|
196
|
+
@previously_changed = ActiveSupport::HashWithIndifferentAccess.new
|
194
197
|
@mutations_before_last_save = nil
|
198
|
+
@attributes_changed_by_setter = ActiveSupport::HashWithIndifferentAccess.new
|
195
199
|
forget_attribute_assignments
|
196
200
|
@mutations_from_database = nil
|
197
201
|
end
|
198
202
|
|
199
203
|
def clear_attribute_changes(attr_names)
|
204
|
+
attributes_changed_by_setter.except!(*attr_names)
|
200
205
|
attr_names.each do |attr_name|
|
201
206
|
clear_attribute_change(attr_name)
|
202
207
|
end
|
@@ -209,7 +214,13 @@ module ActiveModel
|
|
209
214
|
# person.name = 'robert'
|
210
215
|
# person.changed_attributes # => {"name" => "bob"}
|
211
216
|
def changed_attributes
|
212
|
-
|
217
|
+
# This should only be set by methods which will call changed_attributes
|
218
|
+
# multiple times when it is known that the computed value cannot change.
|
219
|
+
if defined?(@cached_changed_attributes)
|
220
|
+
@cached_changed_attributes
|
221
|
+
else
|
222
|
+
attributes_changed_by_setter.reverse_merge(mutations_from_database.changed_values).freeze
|
223
|
+
end
|
213
224
|
end
|
214
225
|
|
215
226
|
# Returns a hash of changed attributes indicating their original
|
@@ -219,8 +230,9 @@ module ActiveModel
|
|
219
230
|
# person.name = 'bob'
|
220
231
|
# person.changes # => { "name" => ["bill", "bob"] }
|
221
232
|
def changes
|
222
|
-
|
223
|
-
|
233
|
+
cache_changed_attributes do
|
234
|
+
ActiveSupport::HashWithIndifferentAccess[changed.map { |attr| [attr, attribute_change(attr)] }]
|
235
|
+
end
|
224
236
|
end
|
225
237
|
|
226
238
|
# Returns a hash of attributes that were changed before the model was saved.
|
@@ -230,7 +242,8 @@ module ActiveModel
|
|
230
242
|
# person.save
|
231
243
|
# person.previous_changes # => {"name" => ["bob", "robert"]}
|
232
244
|
def previous_changes
|
233
|
-
|
245
|
+
@previously_changed ||= ActiveSupport::HashWithIndifferentAccess.new
|
246
|
+
@previously_changed.merge(mutations_before_last_save.changes)
|
234
247
|
end
|
235
248
|
|
236
249
|
def attribute_changed_in_place?(attr_name) # :nodoc:
|
@@ -246,17 +259,11 @@ module ActiveModel
|
|
246
259
|
unless defined?(@mutations_from_database)
|
247
260
|
@mutations_from_database = nil
|
248
261
|
end
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
Hash.new { |h, attr|
|
254
|
-
h[attr] = Attribute.with_cast_value(attr, _clone_attribute(attr), Type.default_value)
|
255
|
-
}
|
256
|
-
)
|
262
|
+
@mutations_from_database ||= if defined?(@attributes)
|
263
|
+
ActiveModel::AttributeMutationTracker.new(@attributes)
|
264
|
+
else
|
265
|
+
NullMutationTracker.instance
|
257
266
|
end
|
258
|
-
|
259
|
-
@mutations_from_database ||= ActiveModel::AttributeMutationTracker.new(@attributes)
|
260
267
|
end
|
261
268
|
|
262
269
|
def forget_attribute_assignments
|
@@ -267,45 +274,68 @@ module ActiveModel
|
|
267
274
|
@mutations_before_last_save ||= ActiveModel::NullMutationTracker.instance
|
268
275
|
end
|
269
276
|
|
277
|
+
def cache_changed_attributes
|
278
|
+
@cached_changed_attributes = changed_attributes
|
279
|
+
yield
|
280
|
+
ensure
|
281
|
+
clear_changed_attributes_cache
|
282
|
+
end
|
283
|
+
|
284
|
+
def clear_changed_attributes_cache
|
285
|
+
remove_instance_variable(:@cached_changed_attributes) if defined?(@cached_changed_attributes)
|
286
|
+
end
|
287
|
+
|
288
|
+
# Returns +true+ if attr_name is changed, +false+ otherwise.
|
289
|
+
def changes_include?(attr_name)
|
290
|
+
attributes_changed_by_setter.include?(attr_name) || mutations_from_database.changed?(attr_name)
|
291
|
+
end
|
292
|
+
alias attribute_changed_by_setter? changes_include?
|
293
|
+
|
294
|
+
# Returns +true+ if attr_name were changed before the model was saved,
|
295
|
+
# +false+ otherwise.
|
296
|
+
def previous_changes_include?(attr_name)
|
297
|
+
previous_changes.include?(attr_name)
|
298
|
+
end
|
299
|
+
|
270
300
|
# Handles <tt>*_change</tt> for +method_missing+.
|
271
301
|
def attribute_change(attr)
|
272
|
-
[
|
302
|
+
[changed_attributes[attr], _read_attribute(attr)] if attribute_changed?(attr)
|
273
303
|
end
|
274
304
|
|
275
305
|
# Handles <tt>*_previous_change</tt> for +method_missing+.
|
276
306
|
def attribute_previous_change(attr)
|
277
|
-
|
307
|
+
previous_changes[attr] if attribute_previously_changed?(attr)
|
278
308
|
end
|
279
309
|
|
280
310
|
# Handles <tt>*_will_change!</tt> for +method_missing+.
|
281
311
|
def attribute_will_change!(attr)
|
282
|
-
|
283
|
-
|
284
|
-
|
312
|
+
unless attribute_changed?(attr)
|
313
|
+
begin
|
314
|
+
value = _read_attribute(attr)
|
315
|
+
value = value.duplicable? ? value.clone : value
|
316
|
+
rescue TypeError, NoMethodError
|
317
|
+
end
|
318
|
+
|
319
|
+
set_attribute_was(attr, value)
|
285
320
|
end
|
321
|
+
mutations_from_database.force_change(attr)
|
286
322
|
end
|
287
323
|
|
288
324
|
# Handles <tt>restore_*!</tt> for +method_missing+.
|
289
325
|
def restore_attribute!(attr)
|
290
326
|
if attribute_changed?(attr)
|
291
|
-
__send__("#{attr}=",
|
327
|
+
__send__("#{attr}=", changed_attributes[attr])
|
292
328
|
clear_attribute_changes([attr])
|
293
329
|
end
|
294
330
|
end
|
295
331
|
|
296
|
-
def
|
297
|
-
|
298
|
-
changed.each do |attr|
|
299
|
-
@attributes.write_from_user(attr, _read_attribute(attr))
|
300
|
-
end
|
301
|
-
end
|
332
|
+
def attributes_changed_by_setter
|
333
|
+
@attributes_changed_by_setter ||= ActiveSupport::HashWithIndifferentAccess.new
|
302
334
|
end
|
303
335
|
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
rescue TypeError, NoMethodError
|
308
|
-
value
|
336
|
+
# Force an attribute to have a particular "before" value
|
337
|
+
def set_attribute_was(attr, old_value)
|
338
|
+
attributes_changed_by_setter[attr] = old_value
|
309
339
|
end
|
310
340
|
end
|
311
341
|
end
|
@@ -179,7 +179,7 @@ module ActiveModel
|
|
179
179
|
return unless includes = options[:include]
|
180
180
|
|
181
181
|
unless includes.is_a?(Hash)
|
182
|
-
includes = Hash[Array(includes).
|
182
|
+
includes = Hash[Array(includes).flat_map { |n| n.is_a?(Hash) ? n.to_a : [[n, {}]] }]
|
183
183
|
end
|
184
184
|
|
185
185
|
includes.each do |association, opts|
|
@@ -28,14 +28,10 @@ module ActiveModel
|
|
28
28
|
private
|
29
29
|
|
30
30
|
def cast_value(value)
|
31
|
-
return value unless value.is_a?(::String)
|
31
|
+
return apply_seconds_precision(value) unless value.is_a?(::String)
|
32
32
|
return if value.empty?
|
33
33
|
|
34
|
-
|
35
|
-
dummy_time_value = value
|
36
|
-
else
|
37
|
-
dummy_time_value = "2000-01-01 #{value}"
|
38
|
-
end
|
34
|
+
dummy_time_value = value.sub(/\A(\d\d\d\d-\d\d-\d\d |)/, "2000-01-01 ")
|
39
35
|
|
40
36
|
fast_string_to_time(dummy_time_value) || begin
|
41
37
|
time_hash = ::Date._parse(dummy_time_value)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activemodel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.2.0.
|
4
|
+
version: 5.2.0.rc2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Heinemeier Hansson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-03-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 5.2.0.
|
19
|
+
version: 5.2.0.rc2
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 5.2.0.
|
26
|
+
version: 5.2.0.rc2
|
27
27
|
description: A toolkit for building modeling frameworks like Active Record. Rich support
|
28
28
|
for attributes, callbacks, validations, serialization, internationalization, and
|
29
29
|
testing.
|
@@ -100,8 +100,8 @@ homepage: http://rubyonrails.org
|
|
100
100
|
licenses:
|
101
101
|
- MIT
|
102
102
|
metadata:
|
103
|
-
source_code_uri: https://github.com/rails/rails/tree/v5.2.0.
|
104
|
-
changelog_uri: https://github.com/rails/rails/blob/v5.2.0.
|
103
|
+
source_code_uri: https://github.com/rails/rails/tree/v5.2.0.rc2/activemodel
|
104
|
+
changelog_uri: https://github.com/rails/rails/blob/v5.2.0.rc2/activemodel/CHANGELOG.md
|
105
105
|
post_install_message:
|
106
106
|
rdoc_options: []
|
107
107
|
require_paths:
|
@@ -118,7 +118,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
118
118
|
version: 1.3.1
|
119
119
|
requirements: []
|
120
120
|
rubyforge_project:
|
121
|
-
rubygems_version: 2.7.
|
121
|
+
rubygems_version: 2.7.6
|
122
122
|
signing_key:
|
123
123
|
specification_version: 4
|
124
124
|
summary: A toolkit for building modeling frameworks (part of Rails).
|