activemodel 5.1.7 → 5.2.0.beta1

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.
Files changed (64) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +32 -93
  3. data/README.rdoc +1 -1
  4. data/lib/active_model.rb +6 -1
  5. data/lib/active_model/attribute.rb +243 -0
  6. data/lib/active_model/attribute/user_provided_default.rb +30 -0
  7. data/lib/active_model/attribute_assignment.rb +8 -5
  8. data/lib/active_model/attribute_methods.rb +12 -10
  9. data/lib/active_model/attribute_mutation_tracker.rb +116 -0
  10. data/lib/active_model/attribute_set.rb +113 -0
  11. data/lib/active_model/attribute_set/builder.rb +124 -0
  12. data/lib/active_model/attribute_set/yaml_encoder.rb +41 -0
  13. data/lib/active_model/attributes.rb +108 -0
  14. data/lib/active_model/callbacks.rb +7 -2
  15. data/lib/active_model/conversion.rb +2 -0
  16. data/lib/active_model/dirty.rb +124 -57
  17. data/lib/active_model/errors.rb +32 -21
  18. data/lib/active_model/forbidden_attributes_protection.rb +2 -0
  19. data/lib/active_model/gem_version.rb +5 -3
  20. data/lib/active_model/lint.rb +2 -0
  21. data/lib/active_model/model.rb +2 -0
  22. data/lib/active_model/naming.rb +5 -3
  23. data/lib/active_model/railtie.rb +2 -0
  24. data/lib/active_model/secure_password.rb +5 -3
  25. data/lib/active_model/serialization.rb +2 -0
  26. data/lib/active_model/serializers/json.rb +3 -2
  27. data/lib/active_model/translation.rb +2 -0
  28. data/lib/active_model/type.rb +6 -0
  29. data/lib/active_model/type/big_integer.rb +2 -0
  30. data/lib/active_model/type/binary.rb +2 -0
  31. data/lib/active_model/type/boolean.rb +2 -0
  32. data/lib/active_model/type/date.rb +2 -0
  33. data/lib/active_model/type/date_time.rb +6 -0
  34. data/lib/active_model/type/decimal.rb +2 -0
  35. data/lib/active_model/type/float.rb +2 -0
  36. data/lib/active_model/type/helpers.rb +2 -0
  37. data/lib/active_model/type/helpers/accepts_multiparameter_time.rb +6 -0
  38. data/lib/active_model/type/helpers/mutable.rb +2 -0
  39. data/lib/active_model/type/helpers/numeric.rb +2 -0
  40. data/lib/active_model/type/helpers/time_value.rb +2 -1
  41. data/lib/active_model/type/immutable_string.rb +2 -0
  42. data/lib/active_model/type/integer.rb +3 -1
  43. data/lib/active_model/type/registry.rb +2 -0
  44. data/lib/active_model/type/string.rb +2 -0
  45. data/lib/active_model/type/time.rb +8 -4
  46. data/lib/active_model/type/value.rb +3 -1
  47. data/lib/active_model/validations.rb +7 -3
  48. data/lib/active_model/validations/absence.rb +2 -0
  49. data/lib/active_model/validations/acceptance.rb +2 -0
  50. data/lib/active_model/validations/callbacks.rb +11 -13
  51. data/lib/active_model/validations/clusivity.rb +2 -0
  52. data/lib/active_model/validations/confirmation.rb +3 -1
  53. data/lib/active_model/validations/exclusion.rb +2 -0
  54. data/lib/active_model/validations/format.rb +1 -0
  55. data/lib/active_model/validations/helper_methods.rb +2 -0
  56. data/lib/active_model/validations/inclusion.rb +2 -0
  57. data/lib/active_model/validations/length.rb +10 -2
  58. data/lib/active_model/validations/numericality.rb +3 -1
  59. data/lib/active_model/validations/presence.rb +1 -0
  60. data/lib/active_model/validations/validates.rb +4 -3
  61. data/lib/active_model/validations/with.rb +2 -0
  62. data/lib/active_model/validator.rb +6 -4
  63. data/lib/active_model/version.rb +2 -0
  64. metadata +17 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: 176c2e4b4046605da54dbff663e8cca4e615bf2f985f11ce19befb86dd54b6e5
4
- data.tar.gz: f94d4e883f254dc43a58abe127653920a852ceb437d2e96163418b3c9f64b273
2
+ SHA1:
3
+ metadata.gz: 9a527b6fc9e7656a84868c763aec48bb368d7bfd
4
+ data.tar.gz: 4c6ebab7e83916520a612437380b074e002f37e1
5
5
  SHA512:
6
- metadata.gz: 2571ca4fd35c99bbf91349f87a261a5e4821f8d2ec9172303c1d85536111ce843305bea423b3794e22a800270b9db8e9f97a23d981ab95ebda973547e8b0ad74
7
- data.tar.gz: ce929044a81485baad038cfa449ee198720ed326afcb0aa3a782da558c7c4569e7f9ee433043fb5f48ddbbdfb26df75d376f2e1e256da13e80a4350126b06722
6
+ metadata.gz: 0671a93f14567ade18a581e3e0c848771e002261eccddcb703aa0b77f9574c1a2d2e091f2f295cafc37ce20e220dc01488b99e14653fb10d4415f4658c5396fb
7
+ data.tar.gz: 1385ef9675c0c9fd44b6acd88f55d3a25db8c0a5e42607b5ae12908e883aea9882c2fa42bcee5e50e585f1c46e023629878ef3bc40764ccb473efc32c81aaec4
@@ -1,112 +1,51 @@
1
- ## Rails 5.1.7 (March 27, 2019) ##
1
+ ## Rails 5.2.0.beta1 (November 27, 2017) ##
2
2
 
3
- * No changes.
3
+ * Execute `ConfirmationValidator` validation when `_confirmation`'s value is `false`.
4
4
 
5
+ *bogdanvlviv*
5
6
 
6
- ## Rails 5.1.6.2 (March 11, 2019) ##
7
+ * Allow passing a Proc or Symbol to length validator options.
7
8
 
8
- * No changes.
9
+ *Matt Rohrer*
9
10
 
11
+ * Add method `#merge!` for `ActiveModel::Errors`.
10
12
 
11
- ## Rails 5.1.6.1 (November 27, 2018) ##
13
+ *Jahfer Husain*
12
14
 
13
- * No changes.
14
-
15
-
16
- ## Rails 5.1.6 (March 29, 2018) ##
17
-
18
- * No changes.
19
-
20
-
21
- ## Rails 5.1.5 (February 14, 2018) ##
22
-
23
- * Fix to working before/after validation callbacks on multiple contexts.
24
-
25
- *Yoshiyuki Hirano*
26
-
27
- ## Rails 5.1.4 (September 07, 2017) ##
28
-
29
- * No changes.
30
-
31
-
32
- ## Rails 5.1.4.rc1 (August 24, 2017) ##
33
-
34
- * No changes.
35
-
36
-
37
- ## Rails 5.1.3 (August 03, 2017) ##
38
-
39
- * No changes.
40
-
41
-
42
- ## Rails 5.1.3.rc3 (July 31, 2017) ##
43
-
44
- * No changes.
45
-
46
-
47
- ## Rails 5.1.3.rc2 (July 25, 2017) ##
48
-
49
- * No changes.
50
-
51
-
52
- ## Rails 5.1.3.rc1 (July 19, 2017) ##
53
-
54
- * No changes.
55
-
56
-
57
- ## Rails 5.1.2 (June 26, 2017) ##
58
-
59
- * Fix regression in numericality validator when comparing Decimal and Float input
15
+ * Fix regression in numericality validator when comparing Decimal and Float input
60
16
  values with more scale than the schema.
61
17
 
62
18
  *Bradley Priest*
63
19
 
20
+ * Fix methods `#keys`, `#values` in `ActiveModel::Errors`.
64
21
 
65
- ## Rails 5.1.1 (May 12, 2017) ##
66
-
67
- * No changes.
68
-
69
-
70
- ## Rails 5.1.0 (April 27, 2017) ##
71
-
72
- * The original string assigned to a model attribute is no longer incorrectly
73
- frozen.
74
-
75
- Fixes #24185, #28718.
76
-
77
- *Matthew Draper*
78
-
79
- * Avoid converting integer as a string into float.
80
-
81
- *namusyaka*
82
-
83
- * Remove deprecated behavior that halts callbacks when the return is false.
84
-
85
- *Rafael Mendonça França*
86
-
87
- * Remove unused `ActiveModel::TestCase` class.
88
-
89
- *Yuji Yaginuma*
90
-
91
- * Moved DecimalWithoutScale, Text, and UnsignedInteger from Active Model to Active Record
92
-
93
- *Iain Beeston*
94
-
95
- * Allow indifferent access in `ActiveModel::Errors`.
96
-
97
- `#include?`, `#has_key?`, `#key?`, `#delete` and `#full_messages_for`.
98
-
99
- *Kenichi Kamiya*
22
+ Change `#keys` to only return the keys that don't have empty messages.
100
23
 
101
- * Removed deprecated `:tokenizer` in the length validator.
24
+ Change `#values` to only return the not empty values.
102
25
 
103
- *Rafael Mendonça França*
26
+ Example:
104
27
 
105
- * Removed deprecated methods in `ActiveModel::Errors`.
28
+ # Before
29
+ person = Person.new
30
+ person.errors.keys # => []
31
+ person.errors.values # => []
32
+ person.errors.messages # => {}
33
+ person.errors[:name] # => []
34
+ person.errors.messages # => {:name => []}
35
+ person.errors.keys # => [:name]
36
+ person.errors.values # => [[]]
106
37
 
107
- `#get`, `#set`, `[]=`, `add_on_empty` and `add_on_blank`.
38
+ # After
39
+ person = Person.new
40
+ person.errors.keys # => []
41
+ person.errors.values # => []
42
+ person.errors.messages # => {}
43
+ person.errors[:name] # => []
44
+ person.errors.messages # => {:name => []}
45
+ person.errors.keys # => []
46
+ person.errors.values # => []
108
47
 
109
- *Rafael Mendonça França*
48
+ *bogdanvlviv*
110
49
 
111
50
 
112
- Please check [5-0-stable](https://github.com/rails/rails/blob/5-0-stable/activemodel/CHANGELOG.md) for previous changes.
51
+ Please check [5-1-stable](https://github.com/rails/rails/blob/5-1-stable/activemodel/CHANGELOG.md) for previous changes.
@@ -246,7 +246,7 @@ Source code can be downloaded as part of the Rails project on GitHub
246
246
 
247
247
  Active Model is released under the MIT license:
248
248
 
249
- * http://www.opensource.org/licenses/MIT
249
+ * https://opensource.org/licenses/MIT
250
250
 
251
251
 
252
252
  == Support
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  #--
2
4
  # Copyright (c) 2004-2017 David Heinemeier Hansson
3
5
  #
@@ -28,6 +30,8 @@ require "active_model/version"
28
30
  module ActiveModel
29
31
  extend ActiveSupport::Autoload
30
32
 
33
+ autoload :Attribute
34
+ autoload :Attributes
31
35
  autoload :AttributeAssignment
32
36
  autoload :AttributeMethods
33
37
  autoload :BlockValidator, "active_model/validator"
@@ -43,6 +47,7 @@ module ActiveModel
43
47
  autoload :SecurePassword
44
48
  autoload :Serialization
45
49
  autoload :Translation
50
+ autoload :Type
46
51
  autoload :Validations
47
52
  autoload :Validator
48
53
 
@@ -68,5 +73,5 @@ module ActiveModel
68
73
  end
69
74
 
70
75
  ActiveSupport.on_load(:i18n) do
71
- I18n.load_path << File.dirname(__FILE__) + "/active_model/locale/en.yml"
76
+ I18n.load_path << File.expand_path("active_model/locale/en.yml", __dir__)
72
77
  end
@@ -0,0 +1,243 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/object/duplicable"
4
+
5
+ module ActiveModel
6
+ class Attribute # :nodoc:
7
+ class << self
8
+ def from_database(name, value, type)
9
+ FromDatabase.new(name, value, type)
10
+ end
11
+
12
+ def from_user(name, value, type, original_attribute = nil)
13
+ FromUser.new(name, value, type, original_attribute)
14
+ end
15
+
16
+ def with_cast_value(name, value, type)
17
+ WithCastValue.new(name, value, type)
18
+ end
19
+
20
+ def null(name)
21
+ Null.new(name)
22
+ end
23
+
24
+ def uninitialized(name, type)
25
+ Uninitialized.new(name, type)
26
+ end
27
+ end
28
+
29
+ attr_reader :name, :value_before_type_cast, :type
30
+
31
+ # This method should not be called directly.
32
+ # Use #from_database or #from_user
33
+ def initialize(name, value_before_type_cast, type, original_attribute = nil)
34
+ @name = name
35
+ @value_before_type_cast = value_before_type_cast
36
+ @type = type
37
+ @original_attribute = original_attribute
38
+ end
39
+
40
+ def value
41
+ # `defined?` is cheaper than `||=` when we get back falsy values
42
+ @value = type_cast(value_before_type_cast) unless defined?(@value)
43
+ @value
44
+ end
45
+
46
+ def original_value
47
+ if assigned?
48
+ original_attribute.original_value
49
+ else
50
+ type_cast(value_before_type_cast)
51
+ end
52
+ end
53
+
54
+ def value_for_database
55
+ type.serialize(value)
56
+ end
57
+
58
+ def changed?
59
+ changed_from_assignment? || changed_in_place?
60
+ end
61
+
62
+ def changed_in_place?
63
+ has_been_read? && type.changed_in_place?(original_value_for_database, value)
64
+ end
65
+
66
+ def forgetting_assignment
67
+ with_value_from_database(value_for_database)
68
+ end
69
+
70
+ def with_value_from_user(value)
71
+ type.assert_valid_value(value)
72
+ self.class.from_user(name, value, type, original_attribute || self)
73
+ end
74
+
75
+ def with_value_from_database(value)
76
+ self.class.from_database(name, value, type)
77
+ end
78
+
79
+ def with_cast_value(value)
80
+ self.class.with_cast_value(name, value, type)
81
+ end
82
+
83
+ def with_type(type)
84
+ if changed_in_place?
85
+ with_value_from_user(value).with_type(type)
86
+ else
87
+ self.class.new(name, value_before_type_cast, type, original_attribute)
88
+ end
89
+ end
90
+
91
+ def type_cast(*)
92
+ raise NotImplementedError
93
+ end
94
+
95
+ def initialized?
96
+ true
97
+ end
98
+
99
+ def came_from_user?
100
+ false
101
+ end
102
+
103
+ def has_been_read?
104
+ defined?(@value)
105
+ end
106
+
107
+ def ==(other)
108
+ self.class == other.class &&
109
+ name == other.name &&
110
+ value_before_type_cast == other.value_before_type_cast &&
111
+ type == other.type
112
+ end
113
+ alias eql? ==
114
+
115
+ def hash
116
+ [self.class, name, value_before_type_cast, type].hash
117
+ end
118
+
119
+ def init_with(coder)
120
+ @name = coder["name"]
121
+ @value_before_type_cast = coder["value_before_type_cast"]
122
+ @type = coder["type"]
123
+ @original_attribute = coder["original_attribute"]
124
+ @value = coder["value"] if coder.map.key?("value")
125
+ end
126
+
127
+ def encode_with(coder)
128
+ coder["name"] = name
129
+ coder["value_before_type_cast"] = value_before_type_cast unless value_before_type_cast.nil?
130
+ coder["type"] = type if type
131
+ coder["original_attribute"] = original_attribute if original_attribute
132
+ coder["value"] = value if defined?(@value)
133
+ end
134
+
135
+ protected
136
+
137
+ attr_reader :original_attribute
138
+ alias_method :assigned?, :original_attribute
139
+
140
+ def original_value_for_database
141
+ if assigned?
142
+ original_attribute.original_value_for_database
143
+ else
144
+ _original_value_for_database
145
+ end
146
+ end
147
+
148
+ private
149
+ def initialize_dup(other)
150
+ if defined?(@value) && @value.duplicable?
151
+ @value = @value.dup
152
+ end
153
+ end
154
+
155
+ def changed_from_assignment?
156
+ assigned? && type.changed?(original_value, value, value_before_type_cast)
157
+ end
158
+
159
+ def _original_value_for_database
160
+ type.serialize(original_value)
161
+ end
162
+
163
+ class FromDatabase < Attribute # :nodoc:
164
+ def type_cast(value)
165
+ type.deserialize(value)
166
+ end
167
+
168
+ def _original_value_for_database
169
+ value_before_type_cast
170
+ end
171
+ end
172
+
173
+ class FromUser < Attribute # :nodoc:
174
+ def type_cast(value)
175
+ type.cast(value)
176
+ end
177
+
178
+ def came_from_user?
179
+ !type.value_constructed_by_mass_assignment?(value_before_type_cast)
180
+ end
181
+ end
182
+
183
+ class WithCastValue < Attribute # :nodoc:
184
+ def type_cast(value)
185
+ value
186
+ end
187
+
188
+ def changed_in_place?
189
+ false
190
+ end
191
+ end
192
+
193
+ class Null < Attribute # :nodoc:
194
+ def initialize(name)
195
+ super(name, nil, Type.default_value)
196
+ end
197
+
198
+ def type_cast(*)
199
+ nil
200
+ end
201
+
202
+ def with_type(type)
203
+ self.class.with_cast_value(name, nil, type)
204
+ end
205
+
206
+ def with_value_from_database(value)
207
+ raise ActiveModel::MissingAttributeError, "can't write unknown attribute `#{name}`"
208
+ end
209
+ alias_method :with_value_from_user, :with_value_from_database
210
+ end
211
+
212
+ class Uninitialized < Attribute # :nodoc:
213
+ UNINITIALIZED_ORIGINAL_VALUE = Object.new
214
+
215
+ def initialize(name, type)
216
+ super(name, nil, type)
217
+ end
218
+
219
+ def value
220
+ if block_given?
221
+ yield name
222
+ end
223
+ end
224
+
225
+ def original_value
226
+ UNINITIALIZED_ORIGINAL_VALUE
227
+ end
228
+
229
+ def value_for_database
230
+ end
231
+
232
+ def initialized?
233
+ false
234
+ end
235
+
236
+ def with_type(type)
237
+ self.class.new(name, type)
238
+ end
239
+ end
240
+
241
+ private_constant :FromDatabase, :FromUser, :Null, :Uninitialized, :WithCastValue
242
+ end
243
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_model/attribute"
4
+
5
+ module ActiveModel
6
+ class Attribute # :nodoc:
7
+ class UserProvidedDefault < FromUser # :nodoc:
8
+ def initialize(name, value, type, database_default)
9
+ @user_provided_value = value
10
+ super(name, value, type, database_default)
11
+ end
12
+
13
+ def value_before_type_cast
14
+ if user_provided_value.is_a?(Proc)
15
+ @memoized_value_before_type_cast ||= user_provided_value.call
16
+ else
17
+ @user_provided_value
18
+ end
19
+ end
20
+
21
+ def with_type(type)
22
+ self.class.new(name, user_provided_value, type, original_attribute)
23
+ end
24
+
25
+ protected
26
+
27
+ attr_reader :user_provided_value
28
+ end
29
+ end
30
+ end