activemodel 5.1.7 → 5.2.0.beta1

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