activemodel 5.2.8 → 6.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +38 -163
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/lib/active_model/attribute/user_provided_default.rb +1 -2
  6. data/lib/active_model/attribute.rb +3 -4
  7. data/lib/active_model/attribute_assignment.rb +1 -1
  8. data/lib/active_model/attribute_methods.rb +39 -1
  9. data/lib/active_model/attribute_mutation_tracker.rb +1 -6
  10. data/lib/active_model/attribute_set/builder.rb +1 -3
  11. data/lib/active_model/attribute_set/yaml_encoder.rb +1 -2
  12. data/lib/active_model/attribute_set.rb +2 -10
  13. data/lib/active_model/attributes.rb +10 -22
  14. data/lib/active_model/callbacks.rb +10 -7
  15. data/lib/active_model/conversion.rb +1 -1
  16. data/lib/active_model/dirty.rb +2 -2
  17. data/lib/active_model/errors.rb +90 -11
  18. data/lib/active_model/gem_version.rb +4 -4
  19. data/lib/active_model/naming.rb +19 -3
  20. data/lib/active_model/railtie.rb +6 -0
  21. data/lib/active_model/secure_password.rb +48 -55
  22. data/lib/active_model/serializers/json.rb +10 -9
  23. data/lib/active_model/type/binary.rb +1 -1
  24. data/lib/active_model/type/boolean.rb +1 -10
  25. data/lib/active_model/type/date.rb +1 -2
  26. data/lib/active_model/type/date_time.rb +3 -4
  27. data/lib/active_model/type/decimal.rb +4 -0
  28. data/lib/active_model/type/helpers/time_value.rb +19 -1
  29. data/lib/active_model/type/helpers.rb +0 -1
  30. data/lib/active_model/type/integer.rb +1 -6
  31. data/lib/active_model/type/registry.rb +2 -10
  32. data/lib/active_model/type/string.rb +2 -2
  33. data/lib/active_model/type/time.rb +0 -5
  34. data/lib/active_model/validations/acceptance.rb +4 -8
  35. data/lib/active_model/validations/clusivity.rb +1 -1
  36. data/lib/active_model/validations/confirmation.rb +2 -2
  37. data/lib/active_model/validations/inclusion.rb +1 -1
  38. data/lib/active_model/validations/numericality.rb +9 -6
  39. data/lib/active_model/validations/validates.rb +2 -2
  40. data/lib/active_model/validations.rb +0 -2
  41. data/lib/active_model/validator.rb +1 -1
  42. data/lib/active_model.rb +1 -1
  43. metadata +10 -11
  44. data/lib/active_model/type/helpers/timezone.rb +0 -19
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7b122429bbe948c048f81b7e6495d78beb2d21ec3d206062cb8b4e73c20ed197
4
- data.tar.gz: 8b09523d536aa75ed116838163ff347c34334a7ae7aa0f486dbca9884e4982ea
3
+ metadata.gz: 69b55e1af8331655f54dbced151a75b1ccbd7e48757fc4a3fd1ee2e5f2236d5a
4
+ data.tar.gz: e756ba5fc97ccd6ee212f32568e58e372b6e94d79082c81711b8e39ac6d86a3a
5
5
  SHA512:
6
- metadata.gz: 3fa058620456e43df5a5785f3e4d7218e6e1b59335c664db15369e662279fdd1cb19143793330791cd4868fae97afc935a8fe632c6c6fdf5fb04b301f74ad796
7
- data.tar.gz: 8c809fe056798699ead24704b2d9bd84f7fd4a6a47b49c4ac1cd61dd7c02cdccde24a0d01cd942f1a819915ea428a84731e33c8ef3d2cd5dc68769c672758431
6
+ metadata.gz: 394b1945a1c68549337a884d68985f0e15c2cbef0e0f968ee50ab55076327e6d55558d9d884d580b7359ea87f460c9a31211090f621f919b3967aa2e9b93188d
7
+ data.tar.gz: 0e1e72d58afc1f7b3f572276c9efa4b21586fa4741d8e31ab2c3bf7bb19e98888f571731d4b5dc04c0ae5f76e5e6c8ee4cf481458eef8e1669c03445277317ec
data/CHANGELOG.md CHANGED
@@ -1,113 +1,17 @@
1
- ## Rails 5.2.8 (May 09, 2022) ##
1
+ ## Rails 6.0.0.beta1 (January 18, 2019) ##
2
2
 
3
- * No changes.
3
+ * Add `ActiveModel::Errors#of_kind?`.
4
4
 
5
-
6
- ## Rails 5.2.7.1 (April 26, 2022) ##
7
-
8
- * No changes.
9
-
10
-
11
- ## Rails 5.2.7 (March 10, 2022) ##
12
-
13
- * No changes.
14
-
15
-
16
- ## Rails 5.2.6.3 (March 08, 2022) ##
17
-
18
- * No changes.
19
-
20
-
21
- ## Rails 5.2.6.2 (February 11, 2022) ##
22
-
23
- * No changes.
24
-
25
-
26
- ## Rails 5.2.6.1 (February 11, 2022) ##
27
-
28
- * No changes.
29
-
30
-
31
- ## Rails 5.2.6 (May 05, 2021) ##
32
-
33
- * No changes.
34
-
35
-
36
- ## Rails 5.2.5 (March 26, 2021) ##
37
-
38
- * No changes.
39
-
40
-
41
- ## Rails 5.2.4.6 (May 05, 2021) ##
42
-
43
- * No changes.
44
-
45
-
46
- ## Rails 5.2.4.5 (February 10, 2021) ##
47
-
48
- * No changes.
49
-
50
-
51
- ## Rails 5.2.4.4 (September 09, 2020) ##
52
-
53
- * No changes.
54
-
55
-
56
- ## Rails 5.2.4.3 (May 18, 2020) ##
57
-
58
- * No changes.
59
-
60
-
61
- ## Rails 5.2.4.2 (March 19, 2020) ##
62
-
63
- * No changes.
64
-
65
-
66
- ## Rails 5.2.4.1 (December 18, 2019) ##
67
-
68
- * No changes.
69
-
70
-
71
- ## Rails 5.2.4 (November 27, 2019) ##
72
-
73
- * Type cast falsy boolean symbols on boolean attribute as false.
74
-
75
- Fixes #35676.
76
-
77
- *Ryuta Kamizono*
78
-
79
-
80
- ## Rails 5.2.3 (March 27, 2019) ##
81
-
82
- * Fix date value when casting a multiparameter date hash to not convert
83
- from Gregorian date to Julian date.
84
-
85
- Before:
86
-
87
- Day.new({"day(1i)"=>"1", "day(2i)"=>"1", "day(3i)"=>"1"})
88
- => #<Day id: nil, day: "0001-01-03", created_at: nil, updated_at: nil>
89
-
90
- After:
91
-
92
- Day.new({"day(1i)"=>"1", "day(2i)"=>"1", "day(3i)"=>"1"})
93
- => #<Day id: nil, day: "0001-01-01", created_at: nil, updated_at: nil>
94
-
95
- Fixes #28521.
96
-
97
- *Sayan Chakraborty*
5
+ *bogdanvlviv*, *Rafael Mendonça França*
98
6
 
99
7
  * Fix numericality equality validation of `BigDecimal` and `Float`
100
8
  by casting to `BigDecimal` on both ends of the validation.
101
9
 
102
10
  *Gannon McGibbon*
103
11
 
12
+ * Add `#slice!` method to `ActiveModel::Errors`.
104
13
 
105
- ## Rails 5.2.2.1 (March 11, 2019) ##
106
-
107
- * No changes.
108
-
109
-
110
- ## Rails 5.2.2 (December 04, 2018) ##
14
+ *Daniel López Prat*
111
15
 
112
16
  * Fix numericality validator to still use value before type cast except Active Record.
113
17
 
@@ -115,79 +19,50 @@
115
19
 
116
20
  *Ryuta Kamizono*
117
21
 
22
+ * Fix `ActiveModel::Serializers::JSON#as_json` method for timestamps.
118
23
 
119
- ## Rails 5.2.1.1 (November 27, 2018) ##
120
-
121
- * No changes.
122
-
123
-
124
- ## Rails 5.2.1 (August 07, 2018) ##
125
-
126
- * No changes.
127
-
128
-
129
- ## Rails 5.2.0 (April 09, 2018) ##
130
-
131
- * Do not lose all multiple `:includes` with options in serialization.
132
-
133
- *Mike Mangino*
134
-
135
- * Models using the attributes API with a proc default can now be marshalled.
136
-
137
- Fixes #31216.
138
-
139
- *Sean Griffin*
140
-
141
- * Fix to working before/after validation callbacks on multiple contexts.
142
-
143
- *Yoshiyuki Hirano*
24
+ Before:
25
+ ```
26
+ contact = Contact.new(created_at: Time.utc(2006, 8, 1))
27
+ contact.as_json["created_at"] # => 2006-08-01 00:00:00 UTC
28
+ ```
144
29
 
145
- * Execute `ConfirmationValidator` validation when `_confirmation`'s value is `false`.
30
+ After:
31
+ ```
32
+ contact = Contact.new(created_at: Time.utc(2006, 8, 1))
33
+ contact.as_json["created_at"] # => "2006-08-01T00:00:00.000Z"
34
+ ```
146
35
 
147
- *bogdanvlviv*
36
+ *Bogdan Gusiev*
148
37
 
149
- * Allow passing a Proc or Symbol to length validator options.
38
+ * Allows configurable attribute name for `#has_secure_password`. This
39
+ still defaults to an attribute named 'password', causing no breaking
40
+ change. There is a new method `#authenticate_XXX` where XXX is the
41
+ configured attribute name, making the existing `#authenticate` now an
42
+ alias for this when the attribute is the default 'password'.
150
43
 
151
- *Matt Rohrer*
44
+ Example:
152
45
 
153
- * Add method `#merge!` for `ActiveModel::Errors`.
46
+ class User < ActiveRecord::Base
47
+ has_secure_password :recovery_password, validations: false
48
+ end
154
49
 
155
- *Jahfer Husain*
50
+ user = User.new()
51
+ user.recovery_password = "42password"
52
+ user.recovery_password_digest # => "$2a$04$iOfhwahFymCs5weB3BNH/uX..."
53
+ user.authenticate_recovery_password('42password') # => user
156
54
 
157
- * Fix regression in numericality validator when comparing Decimal and Float input
158
- values with more scale than the schema.
55
+ *Unathi Chonco*
159
56
 
160
- *Bradley Priest*
57
+ * Add `config.active_model.i18n_full_message` in order to control whether
58
+ the `full_message` error format can be overridden at the attribute or model
59
+ level in the locale files. This is `false` by default.
161
60
 
162
- * Fix methods `#keys`, `#values` in `ActiveModel::Errors`.
61
+ *Martin Larochelle*
163
62
 
164
- Change `#keys` to only return the keys that don't have empty messages.
63
+ * Rails 6 requires Ruby 2.5.0 or newer.
165
64
 
166
- Change `#values` to only return the not empty values.
65
+ *Jeremy Daer*, *Kasper Timm Hansen*
167
66
 
168
- Example:
169
67
 
170
- # Before
171
- person = Person.new
172
- person.errors.keys # => []
173
- person.errors.values # => []
174
- person.errors.messages # => {}
175
- person.errors[:name] # => []
176
- person.errors.messages # => {:name => []}
177
- person.errors.keys # => [:name]
178
- person.errors.values # => [[]]
179
-
180
- # After
181
- person = Person.new
182
- person.errors.keys # => []
183
- person.errors.values # => []
184
- person.errors.messages # => {}
185
- person.errors[:name] # => []
186
- person.errors.messages # => {:name => []}
187
- person.errors.keys # => []
188
- person.errors.values # => []
189
-
190
- *bogdanvlviv*
191
-
192
-
193
- Please check [5-1-stable](https://github.com/rails/rails/blob/5-1-stable/activemodel/CHANGELOG.md) for previous changes.
68
+ Please check [5-2-stable](https://github.com/rails/rails/blob/5-2-stable/activemodel/CHANGELOG.md) for previous changes.
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2004-2018 David Heinemeier Hansson
1
+ Copyright (c) 2004-2019 David Heinemeier Hansson
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
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/5-2-stable/activemodel
242
+ * https://github.com/rails/rails/tree/master/activemodel
243
243
 
244
244
 
245
245
  == License
@@ -44,8 +44,7 @@ module ActiveModel
44
44
  end
45
45
  end
46
46
 
47
- protected
48
-
47
+ private
49
48
  attr_reader :user_provided_value
50
49
  end
51
50
  end
@@ -133,10 +133,6 @@ module ActiveModel
133
133
  end
134
134
 
135
135
  protected
136
-
137
- attr_reader :original_attribute
138
- alias_method :assigned?, :original_attribute
139
-
140
136
  def original_value_for_database
141
137
  if assigned?
142
138
  original_attribute.original_value_for_database
@@ -146,6 +142,9 @@ module ActiveModel
146
142
  end
147
143
 
148
144
  private
145
+ attr_reader :original_attribute
146
+ alias :assigned? :original_attribute
147
+
149
148
  def initialize_dup(other)
150
149
  if defined?(@value) && @value.duplicable?
151
150
  @value = @value.dup
@@ -27,7 +27,7 @@ module ActiveModel
27
27
  # cat.status # => 'sleeping'
28
28
  def assign_attributes(new_attributes)
29
29
  if !new_attributes.respond_to?(:stringify_keys)
30
- raise ArgumentError, "When assigning attributes, you must pass a hash as an argument."
30
+ raise ArgumentError, "When assigning attributes, you must pass a hash as an argument, #{new_attributes.class} passed."
31
31
  end
32
32
  return if new_attributes.empty?
33
33
 
@@ -369,7 +369,7 @@ module ActiveModel
369
369
  "define_method(:'#{name}') do |*args|"
370
370
  end
371
371
 
372
- extra = (extra.map!(&:inspect) << "*args").join(", ".freeze)
372
+ extra = (extra.map!(&:inspect) << "*args").join(", ")
373
373
 
374
374
  target = if CALL_COMPILABLE_REGEXP.match?(send)
375
375
  "#{"self." unless include_private}#{send}(#{extra})"
@@ -474,5 +474,43 @@ module ActiveModel
474
474
  def _read_attribute(attr)
475
475
  __send__(attr)
476
476
  end
477
+
478
+ module AttrNames # :nodoc:
479
+ DEF_SAFE_NAME = /\A[a-zA-Z_]\w*\z/
480
+
481
+ # We want to generate the methods via module_eval rather than
482
+ # define_method, because define_method is slower on dispatch.
483
+ # Evaluating many similar methods may use more memory as the instruction
484
+ # sequences are duplicated and cached (in MRI). define_method may
485
+ # be slower on dispatch, but if you're careful about the closure
486
+ # created, then define_method will consume much less memory.
487
+ #
488
+ # But sometimes the database might return columns with
489
+ # characters that are not allowed in normal method names (like
490
+ # 'my_column(omg)'. So to work around this we first define with
491
+ # the __temp__ identifier, and then use alias method to rename
492
+ # it to what we want.
493
+ #
494
+ # We are also defining a constant to hold the frozen string of
495
+ # the attribute name. Using a constant means that we do not have
496
+ # to allocate an object on each call to the attribute method.
497
+ # Making it frozen means that it doesn't get duped when used to
498
+ # key the @attributes in read_attribute.
499
+ def self.define_attribute_accessor_method(mod, attr_name, writer: false)
500
+ method_name = "#{attr_name}#{'=' if writer}"
501
+ if attr_name.ascii_only? && DEF_SAFE_NAME.match?(attr_name)
502
+ yield method_name, "'#{attr_name}'.freeze"
503
+ else
504
+ safe_name = attr_name.unpack1("h*")
505
+ const_name = "ATTR_#{safe_name}"
506
+ const_set(const_name, attr_name) unless const_defined?(const_name)
507
+ temp_method_name = "__temp__#{safe_name}#{'=' if writer}"
508
+ attr_name_expr = "::ActiveModel::AttributeMethods::AttrNames::#{const_name}"
509
+ yield temp_method_name, attr_name_expr
510
+ mod.alias_method method_name, temp_method_name
511
+ mod.undef_method temp_method_name
512
+ end
513
+ end
514
+ end
477
515
  end
478
516
  end
@@ -69,13 +69,8 @@ module ActiveModel
69
69
  forced_changes << attr_name.to_s
70
70
  end
71
71
 
72
- # TODO Change this to private once we've dropped Ruby 2.2 support.
73
- # Workaround for Ruby 2.2 "private attribute?" warning.
74
- protected
75
-
76
- attr_reader :attributes, :forced_changes
77
-
78
72
  private
73
+ attr_reader :attributes, :forced_changes
79
74
 
80
75
  def attr_names
81
76
  attributes.keys
@@ -90,9 +90,6 @@ module ActiveModel
90
90
  end
91
91
 
92
92
  protected
93
-
94
- attr_reader :types, :values, :additional_types, :delegate_hash, :default_attributes
95
-
96
93
  def materialize
97
94
  unless @materialized
98
95
  values.each_key { |key| self[key] }
@@ -105,6 +102,7 @@ module ActiveModel
105
102
  end
106
103
 
107
104
  private
105
+ attr_reader :types, :values, :additional_types, :delegate_hash, :default_attributes
108
106
 
109
107
  def assign_default_value(name)
110
108
  type = additional_types.fetch(name, types[name])
@@ -33,8 +33,7 @@ module ActiveModel
33
33
  end
34
34
  end
35
35
 
36
- protected
37
-
36
+ private
38
37
  attr_reader :default_types
39
38
  end
40
39
  end
@@ -37,16 +37,8 @@ module ActiveModel
37
37
  attributes.each_key.select { |name| self[name].initialized? }
38
38
  end
39
39
 
40
- if defined?(JRUBY_VERSION)
41
- # This form is significantly faster on JRuby, and this is one of our biggest hotspots.
42
- # https://github.com/jruby/jruby/pull/2562
43
- def fetch_value(name, &block)
44
- self[name].value(&block)
45
- end
46
- else
47
- def fetch_value(name)
48
- self[name].value { |n| yield n if block_given? }
49
- end
40
+ def fetch_value(name, &block)
41
+ self[name].value(&block)
50
42
  end
51
43
 
52
44
  def write_from_database(name, value)
@@ -29,17 +29,16 @@ module ActiveModel
29
29
  private
30
30
 
31
31
  def define_method_attribute=(name)
32
- safe_name = name.unpack("h*".freeze).first
33
- ActiveModel::AttributeMethods::AttrNames.set_name_cache safe_name, name
34
-
35
- generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
36
- def __temp__#{safe_name}=(value)
37
- name = ::ActiveModel::AttributeMethods::AttrNames::ATTR_#{safe_name}
38
- write_attribute(name, value)
39
- end
40
- alias_method #{(name + '=').inspect}, :__temp__#{safe_name}=
41
- undef_method :__temp__#{safe_name}=
42
- STR
32
+ ActiveModel::AttributeMethods::AttrNames.define_attribute_accessor_method(
33
+ generated_attribute_methods, name, writer: true,
34
+ ) do |temp_method_name, attr_name_expr|
35
+ generated_attribute_methods.module_eval <<-RUBY, __FILE__, __LINE__ + 1
36
+ def #{temp_method_name}(value)
37
+ name = #{attr_name_expr}
38
+ write_attribute(name, value)
39
+ end
40
+ RUBY
41
+ end
43
42
  end
44
43
 
45
44
  NO_DEFAULT_PROVIDED = Object.new # :nodoc:
@@ -97,15 +96,4 @@ module ActiveModel
97
96
  write_attribute(attribute_name, value)
98
97
  end
99
98
  end
100
-
101
- module AttributeMethods #:nodoc:
102
- AttrNames = Module.new {
103
- def self.set_name_cache(name, value)
104
- const_name = "ATTR_#{name}"
105
- unless const_defined? const_name
106
- const_set const_name, value.dup.freeze
107
- end
108
- end
109
- }
110
- end
111
99
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/core_ext/array/extract_options"
4
+ require "active_support/core_ext/hash/keys"
4
5
 
5
6
  module ActiveModel
6
7
  # == Active \Model \Callbacks
@@ -127,26 +128,28 @@ module ActiveModel
127
128
  private
128
129
 
129
130
  def _define_before_model_callback(klass, callback)
130
- klass.define_singleton_method("before_#{callback}") do |*args, &block|
131
- set_callback(:"#{callback}", :before, *args, &block)
131
+ klass.define_singleton_method("before_#{callback}") do |*args, **options, &block|
132
+ options.assert_valid_keys(:if, :unless, :prepend)
133
+ set_callback(:"#{callback}", :before, *args, options, &block)
132
134
  end
133
135
  end
134
136
 
135
137
  def _define_around_model_callback(klass, callback)
136
- klass.define_singleton_method("around_#{callback}") do |*args, &block|
137
- set_callback(:"#{callback}", :around, *args, &block)
138
+ klass.define_singleton_method("around_#{callback}") do |*args, **options, &block|
139
+ options.assert_valid_keys(:if, :unless, :prepend)
140
+ set_callback(:"#{callback}", :around, *args, options, &block)
138
141
  end
139
142
  end
140
143
 
141
144
  def _define_after_model_callback(klass, callback)
142
- klass.define_singleton_method("after_#{callback}") do |*args, &block|
143
- options = args.extract_options!
145
+ klass.define_singleton_method("after_#{callback}") do |*args, **options, &block|
146
+ options.assert_valid_keys(:if, :unless, :prepend)
144
147
  options[:prepend] = true
145
148
  conditional = ActiveSupport::Callbacks::Conditionals::Value.new { |v|
146
149
  v != false
147
150
  }
148
151
  options[:if] = Array(options[:if]) << conditional
149
- set_callback(:"#{callback}", :after, *(args << options), &block)
152
+ set_callback(:"#{callback}", :after, *args, options, &block)
150
153
  end
151
154
  end
152
155
  end
@@ -103,7 +103,7 @@ module ActiveModel
103
103
  @_to_partial_path ||= begin
104
104
  element = ActiveSupport::Inflector.underscore(ActiveSupport::Inflector.demodulize(name))
105
105
  collection = ActiveSupport::Inflector.tableize(name)
106
- "#{collection}/#{element}".freeze
106
+ "#{collection}/#{element}"
107
107
  end
108
108
  end
109
109
  end
@@ -153,7 +153,7 @@ module ActiveModel
153
153
  @mutations_from_database = nil
154
154
  end
155
155
 
156
- # Returns +true+ if any of the attributes have unsaved changes, +false+ otherwise.
156
+ # Returns +true+ if any of the attributes has unsaved changes, +false+ otherwise.
157
157
  #
158
158
  # person.changed? # => false
159
159
  # person.name = 'bob'
@@ -306,7 +306,7 @@ module ActiveModel
306
306
 
307
307
  # Handles <tt>*_previous_change</tt> for +method_missing+.
308
308
  def attribute_previous_change(attr)
309
- previous_changes[attr] if attribute_previously_changed?(attr)
309
+ previous_changes[attr]
310
310
  end
311
311
 
312
312
  # Handles <tt>*_will_change!</tt> for +method_missing+.