activemodel 6.0.0

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 (67) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +172 -0
  3. data/MIT-LICENSE +21 -0
  4. data/README.rdoc +266 -0
  5. data/lib/active_model.rb +77 -0
  6. data/lib/active_model/attribute.rb +247 -0
  7. data/lib/active_model/attribute/user_provided_default.rb +51 -0
  8. data/lib/active_model/attribute_assignment.rb +57 -0
  9. data/lib/active_model/attribute_methods.rb +517 -0
  10. data/lib/active_model/attribute_mutation_tracker.rb +178 -0
  11. data/lib/active_model/attribute_set.rb +106 -0
  12. data/lib/active_model/attribute_set/builder.rb +124 -0
  13. data/lib/active_model/attribute_set/yaml_encoder.rb +40 -0
  14. data/lib/active_model/attributes.rb +138 -0
  15. data/lib/active_model/callbacks.rb +156 -0
  16. data/lib/active_model/conversion.rb +111 -0
  17. data/lib/active_model/dirty.rb +280 -0
  18. data/lib/active_model/errors.rb +601 -0
  19. data/lib/active_model/forbidden_attributes_protection.rb +31 -0
  20. data/lib/active_model/gem_version.rb +17 -0
  21. data/lib/active_model/lint.rb +118 -0
  22. data/lib/active_model/locale/en.yml +36 -0
  23. data/lib/active_model/model.rb +99 -0
  24. data/lib/active_model/naming.rb +334 -0
  25. data/lib/active_model/railtie.rb +20 -0
  26. data/lib/active_model/secure_password.rb +128 -0
  27. data/lib/active_model/serialization.rb +192 -0
  28. data/lib/active_model/serializers/json.rb +147 -0
  29. data/lib/active_model/translation.rb +70 -0
  30. data/lib/active_model/type.rb +53 -0
  31. data/lib/active_model/type/big_integer.rb +15 -0
  32. data/lib/active_model/type/binary.rb +52 -0
  33. data/lib/active_model/type/boolean.rb +47 -0
  34. data/lib/active_model/type/date.rb +53 -0
  35. data/lib/active_model/type/date_time.rb +47 -0
  36. data/lib/active_model/type/decimal.rb +70 -0
  37. data/lib/active_model/type/float.rb +34 -0
  38. data/lib/active_model/type/helpers.rb +7 -0
  39. data/lib/active_model/type/helpers/accepts_multiparameter_time.rb +45 -0
  40. data/lib/active_model/type/helpers/mutable.rb +20 -0
  41. data/lib/active_model/type/helpers/numeric.rb +44 -0
  42. data/lib/active_model/type/helpers/time_value.rb +81 -0
  43. data/lib/active_model/type/helpers/timezone.rb +19 -0
  44. data/lib/active_model/type/immutable_string.rb +32 -0
  45. data/lib/active_model/type/integer.rb +58 -0
  46. data/lib/active_model/type/registry.rb +62 -0
  47. data/lib/active_model/type/string.rb +26 -0
  48. data/lib/active_model/type/time.rb +47 -0
  49. data/lib/active_model/type/value.rb +126 -0
  50. data/lib/active_model/validations.rb +437 -0
  51. data/lib/active_model/validations/absence.rb +33 -0
  52. data/lib/active_model/validations/acceptance.rb +102 -0
  53. data/lib/active_model/validations/callbacks.rb +122 -0
  54. data/lib/active_model/validations/clusivity.rb +54 -0
  55. data/lib/active_model/validations/confirmation.rb +80 -0
  56. data/lib/active_model/validations/exclusion.rb +49 -0
  57. data/lib/active_model/validations/format.rb +114 -0
  58. data/lib/active_model/validations/helper_methods.rb +15 -0
  59. data/lib/active_model/validations/inclusion.rb +47 -0
  60. data/lib/active_model/validations/length.rb +129 -0
  61. data/lib/active_model/validations/numericality.rb +189 -0
  62. data/lib/active_model/validations/presence.rb +39 -0
  63. data/lib/active_model/validations/validates.rb +174 -0
  64. data/lib/active_model/validations/with.rb +147 -0
  65. data/lib/active_model/validator.rb +183 -0
  66. data/lib/active_model/version.rb +10 -0
  67. metadata +125 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 69a5bee0cfba77f4724c2db8488624ecf96cf07711dcdc049dd0c3dc63ee5511
4
+ data.tar.gz: 19750eda0fd5b204ae2825c05808351c33a5c73b94e46e5cc6a083e7f71392f3
5
+ SHA512:
6
+ metadata.gz: 0717aa6a3b1c7d833939ce27faf0f2603dfa37c4b07cc67c3e87d4ab596fb086a4da1d719943b6d16fd679dbafdb227f9221d22822359b4c355d398e3bc35850
7
+ data.tar.gz: 325635123b6a4f68f09fe7ae5c5606cdadef8c011e890a54b638bd91bb272c9e45de3d7eda403ad291c365463891d420d2212dcfdefd9212717ddc255c296f1d
@@ -0,0 +1,172 @@
1
+ ## Rails 6.0.0 (August 16, 2019) ##
2
+
3
+ * No changes.
4
+
5
+
6
+ ## Rails 6.0.0.rc2 (July 22, 2019) ##
7
+
8
+ * No changes.
9
+
10
+
11
+ ## Rails 6.0.0.rc1 (April 24, 2019) ##
12
+
13
+ * Type cast falsy boolean symbols on boolean attribute as false.
14
+
15
+ Fixes #35676.
16
+
17
+ *Ryuta Kamizono*
18
+
19
+ * Change how validation error translation strings are fetched: The new behavior
20
+ will first try the more specific keys, including doing locale fallback, then try
21
+ the less specific ones.
22
+
23
+ For example, this is the order in which keys will now be tried for a `blank`
24
+ error on a `product`'s `title` attribute with current locale set to `en-US`:
25
+
26
+ en-US.activerecord.errors.models.product.attributes.title.blank
27
+ en-US.activerecord.errors.models.product.blank
28
+ en-US.activerecord.errors.messages.blank
29
+
30
+ en.activerecord.errors.models.product.attributes.title.blank
31
+ en.activerecord.errors.models.product.blank
32
+ en.activerecord.errors.messages.blank
33
+
34
+ en-US.errors.attributes.title.blank
35
+ en-US.errors.messages.blank
36
+
37
+ en.errors.attributes.title.blank
38
+ en.errors.messages.blank
39
+
40
+ *Hugo Vacher*
41
+
42
+
43
+ ## Rails 6.0.0.beta3 (March 11, 2019) ##
44
+
45
+ * No changes.
46
+
47
+
48
+ ## Rails 6.0.0.beta2 (February 25, 2019) ##
49
+
50
+ * Fix date value when casting a multiparameter date hash to not convert
51
+ from Gregorian date to Julian date.
52
+
53
+ Before:
54
+
55
+ Day.new({"day(1i)"=>"1", "day(2i)"=>"1", "day(3i)"=>"1"})
56
+ # => #<Day id: nil, day: "0001-01-03", created_at: nil, updated_at: nil>
57
+
58
+ After:
59
+
60
+ Day.new({"day(1i)"=>"1", "day(2i)"=>"1", "day(3i)"=>"1"})
61
+ # => #<Day id: nil, day: "0001-01-01", created_at: nil, updated_at: nil>
62
+
63
+ Fixes #28521.
64
+
65
+ *Sayan Chakraborty*
66
+
67
+ * Fix year value when casting a multiparameter time hash.
68
+
69
+ When assigning a hash to a time attribute that's missing a year component
70
+ (e.g. a `time_select` with `:ignore_date` set to `true`) then the year
71
+ defaults to 1970 instead of the expected 2000. This results in the attribute
72
+ changing as a result of the save.
73
+
74
+ Before:
75
+ ```
76
+ event = Event.new(start_time: { 4 => 20, 5 => 30 })
77
+ event.start_time # => 1970-01-01 20:30:00 UTC
78
+ event.save
79
+ event.reload
80
+ event.start_time # => 2000-01-01 20:30:00 UTC
81
+ ```
82
+
83
+ After:
84
+ ```
85
+ event = Event.new(start_time: { 4 => 20, 5 => 30 })
86
+ event.start_time # => 2000-01-01 20:30:00 UTC
87
+ event.save
88
+ event.reload
89
+ event.start_time # => 2000-01-01 20:30:00 UTC
90
+ ```
91
+
92
+ *Andrew White*
93
+
94
+
95
+ ## Rails 6.0.0.beta1 (January 18, 2019) ##
96
+
97
+ * Internal calls to `human_attribute_name` on an `Active Model` now pass attributes as strings instead of symbols
98
+ in some cases.
99
+
100
+ This is in line with examples in Rails docs and puts the code in line with the intention -
101
+ the potential use of strings or symbols.
102
+
103
+ It is recommended to cast the attribute input to your desired type as if you you are overriding that methid.
104
+
105
+ *Martin Larochelle*
106
+
107
+ * Add `ActiveModel::Errors#of_kind?`.
108
+
109
+ *bogdanvlviv*, *Rafael Mendonça França*
110
+
111
+ * Fix numericality equality validation of `BigDecimal` and `Float`
112
+ by casting to `BigDecimal` on both ends of the validation.
113
+
114
+ *Gannon McGibbon*
115
+
116
+ * Add `#slice!` method to `ActiveModel::Errors`.
117
+
118
+ *Daniel López Prat*
119
+
120
+ * Fix numericality validator to still use value before type cast except Active Record.
121
+
122
+ Fixes #33651, #33686.
123
+
124
+ *Ryuta Kamizono*
125
+
126
+ * Fix `ActiveModel::Serializers::JSON#as_json` method for timestamps.
127
+
128
+ Before:
129
+ ```
130
+ contact = Contact.new(created_at: Time.utc(2006, 8, 1))
131
+ contact.as_json["created_at"] # => 2006-08-01 00:00:00 UTC
132
+ ```
133
+
134
+ After:
135
+ ```
136
+ contact = Contact.new(created_at: Time.utc(2006, 8, 1))
137
+ contact.as_json["created_at"] # => "2006-08-01T00:00:00.000Z"
138
+ ```
139
+
140
+ *Bogdan Gusiev*
141
+
142
+ * Allows configurable attribute name for `#has_secure_password`. This
143
+ still defaults to an attribute named 'password', causing no breaking
144
+ change. There is a new method `#authenticate_XXX` where XXX is the
145
+ configured attribute name, making the existing `#authenticate` now an
146
+ alias for this when the attribute is the default 'password'.
147
+
148
+ Example:
149
+
150
+ class User < ActiveRecord::Base
151
+ has_secure_password :recovery_password, validations: false
152
+ end
153
+
154
+ user = User.new()
155
+ user.recovery_password = "42password"
156
+ user.recovery_password_digest # => "$2a$04$iOfhwahFymCs5weB3BNH/uX..."
157
+ user.authenticate_recovery_password('42password') # => user
158
+
159
+ *Unathi Chonco*
160
+
161
+ * Add `config.active_model.i18n_customize_full_message` in order to control whether
162
+ the `full_message` error format can be overridden at the attribute or model
163
+ level in the locale files. This is `false` by default.
164
+
165
+ *Martin Larochelle*
166
+
167
+ * Rails 6 requires Ruby 2.5.0 or newer.
168
+
169
+ *Jeremy Daer*, *Kasper Timm Hansen*
170
+
171
+
172
+ Please check [5-2-stable](https://github.com/rails/rails/blob/5-2-stable/activemodel/CHANGELOG.md) for previous changes.
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2004-2019 David Heinemeier Hansson
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
@@ -0,0 +1,266 @@
1
+ = Active Model -- model interfaces for Rails
2
+
3
+ Active Model provides a known set of interfaces for usage in model classes.
4
+ They allow for Action Pack helpers to interact with non-Active Record models,
5
+ for example. Active Model also helps with building custom ORMs for use outside of
6
+ the Rails framework.
7
+
8
+ You can read more about Active Model in the {Active Model Basics}[https://edgeguides.rubyonrails.org/active_model_basics.html] guide.
9
+
10
+ Prior to Rails 3.0, if a plugin or gem developer wanted to have an object
11
+ interact with Action Pack helpers, it was required to either copy chunks of
12
+ code from Rails, or monkey patch entire helpers to make them handle objects
13
+ that did not exactly conform to the Active Record interface. This would result
14
+ in code duplication and fragile applications that broke on upgrades. Active
15
+ Model solves this by defining an explicit API. You can read more about the
16
+ API in <tt>ActiveModel::Lint::Tests</tt>.
17
+
18
+ Active Model provides a default module that implements the basic API required
19
+ to integrate with Action Pack out of the box: <tt>ActiveModel::Model</tt>.
20
+
21
+ class Person
22
+ include ActiveModel::Model
23
+
24
+ attr_accessor :name, :age
25
+ validates_presence_of :name
26
+ end
27
+
28
+ person = Person.new(name: 'bob', age: '18')
29
+ person.name # => 'bob'
30
+ person.age # => '18'
31
+ person.valid? # => true
32
+
33
+ It includes model name introspections, conversions, translations and
34
+ validations, resulting in a class suitable to be used with Action Pack.
35
+ See <tt>ActiveModel::Model</tt> for more examples.
36
+
37
+ Active Model also provides the following functionality to have ORM-like
38
+ behavior out of the box:
39
+
40
+ * Add attribute magic to objects
41
+
42
+ class Person
43
+ include ActiveModel::AttributeMethods
44
+
45
+ attribute_method_prefix 'clear_'
46
+ define_attribute_methods :name, :age
47
+
48
+ attr_accessor :name, :age
49
+
50
+ def clear_attribute(attr)
51
+ send("#{attr}=", nil)
52
+ end
53
+ end
54
+
55
+ person = Person.new
56
+ person.clear_name
57
+ person.clear_age
58
+
59
+ {Learn more}[link:classes/ActiveModel/AttributeMethods.html]
60
+
61
+ * Callbacks for certain operations
62
+
63
+ class Person
64
+ extend ActiveModel::Callbacks
65
+ define_model_callbacks :create
66
+
67
+ def create
68
+ run_callbacks :create do
69
+ # Your create action methods here
70
+ end
71
+ end
72
+ end
73
+
74
+ This generates +before_create+, +around_create+ and +after_create+
75
+ class methods that wrap your create method.
76
+
77
+ {Learn more}[link:classes/ActiveModel/Callbacks.html]
78
+
79
+ * Tracking value changes
80
+
81
+ class Person
82
+ include ActiveModel::Dirty
83
+
84
+ define_attribute_methods :name
85
+
86
+ def name
87
+ @name
88
+ end
89
+
90
+ def name=(val)
91
+ name_will_change! unless val == @name
92
+ @name = val
93
+ end
94
+
95
+ def save
96
+ # do persistence work
97
+ changes_applied
98
+ end
99
+ end
100
+
101
+ person = Person.new
102
+ person.name # => nil
103
+ person.changed? # => false
104
+ person.name = 'bob'
105
+ person.changed? # => true
106
+ person.changed # => ['name']
107
+ person.changes # => { 'name' => [nil, 'bob'] }
108
+ person.save
109
+ person.name = 'robert'
110
+ person.save
111
+ person.previous_changes # => {'name' => ['bob, 'robert']}
112
+
113
+ {Learn more}[link:classes/ActiveModel/Dirty.html]
114
+
115
+ * Adding +errors+ interface to objects
116
+
117
+ Exposing error messages allows objects to interact with Action Pack
118
+ helpers seamlessly.
119
+
120
+ class Person
121
+
122
+ def initialize
123
+ @errors = ActiveModel::Errors.new(self)
124
+ end
125
+
126
+ attr_accessor :name
127
+ attr_reader :errors
128
+
129
+ def validate!
130
+ errors.add(:name, "cannot be nil") if name.nil?
131
+ end
132
+
133
+ def self.human_attribute_name(attr, options = {})
134
+ "Name"
135
+ end
136
+ end
137
+
138
+ person = Person.new
139
+ person.name = nil
140
+ person.validate!
141
+ person.errors.full_messages
142
+ # => ["Name cannot be nil"]
143
+
144
+ {Learn more}[link:classes/ActiveModel/Errors.html]
145
+
146
+ * Model name introspection
147
+
148
+ class NamedPerson
149
+ extend ActiveModel::Naming
150
+ end
151
+
152
+ NamedPerson.model_name.name # => "NamedPerson"
153
+ NamedPerson.model_name.human # => "Named person"
154
+
155
+ {Learn more}[link:classes/ActiveModel/Naming.html]
156
+
157
+ * Making objects serializable
158
+
159
+ <tt>ActiveModel::Serialization</tt> provides a standard interface for your object
160
+ to provide +to_json+ serialization.
161
+
162
+ class SerialPerson
163
+ include ActiveModel::Serialization
164
+
165
+ attr_accessor :name
166
+
167
+ def attributes
168
+ {'name' => name}
169
+ end
170
+ end
171
+
172
+ s = SerialPerson.new
173
+ s.serializable_hash # => {"name"=>nil}
174
+
175
+ class SerialPerson
176
+ include ActiveModel::Serializers::JSON
177
+ end
178
+
179
+ s = SerialPerson.new
180
+ s.to_json # => "{\"name\":null}"
181
+
182
+ {Learn more}[link:classes/ActiveModel/Serialization.html]
183
+
184
+ * Internationalization (i18n) support
185
+
186
+ class Person
187
+ extend ActiveModel::Translation
188
+ end
189
+
190
+ Person.human_attribute_name('my_attribute')
191
+ # => "My attribute"
192
+
193
+ {Learn more}[link:classes/ActiveModel/Translation.html]
194
+
195
+ * Validation support
196
+
197
+ class Person
198
+ include ActiveModel::Validations
199
+
200
+ attr_accessor :first_name, :last_name
201
+
202
+ validates_each :first_name, :last_name do |record, attr, value|
203
+ record.errors.add attr, 'starts with z.' if value.to_s[0] == ?z
204
+ end
205
+ end
206
+
207
+ person = Person.new
208
+ person.first_name = 'zoolander'
209
+ person.valid? # => false
210
+
211
+ {Learn more}[link:classes/ActiveModel/Validations.html]
212
+
213
+ * Custom validators
214
+
215
+ class HasNameValidator < ActiveModel::Validator
216
+ def validate(record)
217
+ record.errors.add(:name, "must exist") if record.name.blank?
218
+ end
219
+ end
220
+
221
+ class ValidatorPerson
222
+ include ActiveModel::Validations
223
+ validates_with HasNameValidator
224
+ attr_accessor :name
225
+ end
226
+
227
+ p = ValidatorPerson.new
228
+ p.valid? # => false
229
+ p.errors.full_messages # => ["Name must exist"]
230
+ p.name = "Bob"
231
+ p.valid? # => true
232
+
233
+ {Learn more}[link:classes/ActiveModel/Validator.html]
234
+
235
+
236
+ == Download and installation
237
+
238
+ The latest version of Active Model can be installed with RubyGems:
239
+
240
+ $ gem install activemodel
241
+
242
+ Source code can be downloaded as part of the Rails project on GitHub
243
+
244
+ * https://github.com/rails/rails/tree/master/activemodel
245
+
246
+
247
+ == License
248
+
249
+ Active Model is released under the MIT license:
250
+
251
+ * https://opensource.org/licenses/MIT
252
+
253
+
254
+ == Support
255
+
256
+ API documentation is at:
257
+
258
+ * https://api.rubyonrails.org
259
+
260
+ Bug reports for the Ruby on Rails project can be filed here:
261
+
262
+ * https://github.com/rails/rails/issues
263
+
264
+ Feature requests should be discussed on the rails-core mailing list here:
265
+
266
+ * https://groups.google.com/forum/?fromgroups#!forum/rubyonrails-core