activemodel 5.0.7.2 → 5.1.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 (60) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +15 -219
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/lib/active_model.rb +11 -12
  6. data/lib/active_model/attribute_assignment.rb +11 -11
  7. data/lib/active_model/attribute_methods.rb +13 -15
  8. data/lib/active_model/callbacks.rb +19 -20
  9. data/lib/active_model/conversion.rb +12 -3
  10. data/lib/active_model/dirty.rb +14 -14
  11. data/lib/active_model/errors.rb +27 -103
  12. data/lib/active_model/forbidden_attributes_protection.rb +1 -1
  13. data/lib/active_model/gem_version.rb +3 -3
  14. data/lib/active_model/lint.rb +0 -1
  15. data/lib/active_model/model.rb +3 -4
  16. data/lib/active_model/naming.rb +9 -10
  17. data/lib/active_model/secure_password.rb +1 -1
  18. data/lib/active_model/serialization.rb +2 -2
  19. data/lib/active_model/serializers/json.rb +2 -2
  20. data/lib/active_model/translation.rb +2 -3
  21. data/lib/active_model/type.rb +15 -19
  22. data/lib/active_model/type/big_integer.rb +4 -4
  23. data/lib/active_model/type/binary.rb +1 -1
  24. data/lib/active_model/type/boolean.rb +20 -9
  25. data/lib/active_model/type/date.rb +25 -25
  26. data/lib/active_model/type/date_time.rb +21 -21
  27. data/lib/active_model/type/decimal.rb +35 -39
  28. data/lib/active_model/type/float.rb +17 -8
  29. data/lib/active_model/type/helpers.rb +4 -4
  30. data/lib/active_model/type/helpers/accepts_multiparameter_time.rb +2 -2
  31. data/lib/active_model/type/helpers/mutable.rb +2 -2
  32. data/lib/active_model/type/helpers/numeric.rb +18 -17
  33. data/lib/active_model/type/helpers/time_value.rb +23 -23
  34. data/lib/active_model/type/immutable_string.rb +9 -8
  35. data/lib/active_model/type/integer.rb +23 -21
  36. data/lib/active_model/type/registry.rb +12 -8
  37. data/lib/active_model/type/string.rb +1 -6
  38. data/lib/active_model/type/time.rb +15 -11
  39. data/lib/active_model/type/value.rb +6 -6
  40. data/lib/active_model/validations.rb +9 -12
  41. data/lib/active_model/validations/absence.rb +1 -1
  42. data/lib/active_model/validations/acceptance.rb +41 -40
  43. data/lib/active_model/validations/callbacks.rb +4 -7
  44. data/lib/active_model/validations/clusivity.rb +7 -7
  45. data/lib/active_model/validations/confirmation.rb +15 -16
  46. data/lib/active_model/validations/exclusion.rb +1 -2
  47. data/lib/active_model/validations/format.rb +24 -24
  48. data/lib/active_model/validations/inclusion.rb +1 -2
  49. data/lib/active_model/validations/length.rb +6 -42
  50. data/lib/active_model/validations/numericality.rb +3 -11
  51. data/lib/active_model/validations/presence.rb +1 -2
  52. data/lib/active_model/validations/validates.rb +6 -6
  53. data/lib/active_model/validations/with.rb +4 -2
  54. data/lib/active_model/validator.rb +5 -6
  55. data/lib/active_model/version.rb +1 -1
  56. metadata +8 -11
  57. data/lib/active_model/test_case.rb +0 -4
  58. data/lib/active_model/type/decimal_without_scale.rb +0 -11
  59. data/lib/active_model/type/text.rb +0 -11
  60. data/lib/active_model/type/unsigned_integer.rb +0 -15
@@ -1,7 +1,7 @@
1
1
  module ActiveModel
2
2
  module Type
3
- module Helpers
4
- module Mutable # :nodoc:
3
+ module Helpers # :nodoc: all
4
+ module Mutable
5
5
  def cast(value)
6
6
  deserialize(serialize(value))
7
7
  end
@@ -1,14 +1,15 @@
1
1
  module ActiveModel
2
2
  module Type
3
- module Helpers
4
- module Numeric # :nodoc:
3
+ module Helpers # :nodoc: all
4
+ module Numeric
5
5
  def cast(value)
6
- value = case value
7
- when true then 1
8
- when false then 0
9
- when ::String then value.presence
10
- else value
11
- end
6
+ value = \
7
+ case value
8
+ when true then 1
9
+ when false then 0
10
+ when ::String then value.presence
11
+ else value
12
+ end
12
13
  super(value)
13
14
  end
14
15
 
@@ -18,16 +19,16 @@ module ActiveModel
18
19
 
19
20
  private
20
21
 
21
- def number_to_non_number?(old_value, new_value_before_type_cast)
22
- old_value != nil && non_numeric_string?(new_value_before_type_cast)
23
- end
22
+ def number_to_non_number?(old_value, new_value_before_type_cast)
23
+ old_value != nil && non_numeric_string?(new_value_before_type_cast)
24
+ end
24
25
 
25
- def non_numeric_string?(value)
26
- # 'wibble'.to_i will give zero, we want to make sure
27
- # that we aren't marking int zero to string zero as
28
- # changed.
29
- value.to_s !~ /\A-?\d+\.?\d*\z/
30
- end
26
+ def non_numeric_string?(value)
27
+ # 'wibble'.to_i will give zero, we want to make sure
28
+ # that we aren't marking int zero to string zero as
29
+ # changed.
30
+ value.to_s !~ /\A-?\d+\.?\d*\z/
31
+ end
31
32
  end
32
33
  end
33
34
  end
@@ -2,8 +2,8 @@ require "active_support/core_ext/time/zones"
2
2
 
3
3
  module ActiveModel
4
4
  module Type
5
- module Helpers
6
- module TimeValue # :nodoc:
5
+ module Helpers # :nodoc: all
6
+ module TimeValue
7
7
  def serialize(value)
8
8
  value = apply_seconds_precision(value)
9
9
 
@@ -19,7 +19,7 @@ module ActiveModel
19
19
  end
20
20
 
21
21
  def is_utc?
22
- ::Time.zone_default.nil? || ::Time.zone_default =~ 'UTC'
22
+ ::Time.zone_default.nil? || ::Time.zone_default =~ "UTC"
23
23
  end
24
24
 
25
25
  def default_timezone
@@ -33,8 +33,8 @@ module ActiveModel
33
33
  def apply_seconds_precision(value)
34
34
  return value unless precision && value.respond_to?(:usec)
35
35
  number_of_insignificant_digits = 6 - precision
36
- round_power = 10 ** number_of_insignificant_digits
37
- value.change(usec: value.usec / round_power * round_power)
36
+ round_power = 10**number_of_insignificant_digits
37
+ value.change(usec: value.usec - value.usec % round_power)
38
38
  end
39
39
 
40
40
  def type_cast_for_schema(value)
@@ -47,30 +47,30 @@ module ActiveModel
47
47
 
48
48
  private
49
49
 
50
- def new_time(year, mon, mday, hour, min, sec, microsec, offset = nil)
51
- # Treat 0000-00-00 00:00:00 as nil.
52
- return if year.nil? || (year == 0 && mon == 0 && mday == 0)
50
+ def new_time(year, mon, mday, hour, min, sec, microsec, offset = nil)
51
+ # Treat 0000-00-00 00:00:00 as nil.
52
+ return if year.nil? || (year == 0 && mon == 0 && mday == 0)
53
53
 
54
- if offset
55
- time = ::Time.utc(year, mon, mday, hour, min, sec, microsec) rescue nil
56
- return unless time
54
+ if offset
55
+ time = ::Time.utc(year, mon, mday, hour, min, sec, microsec) rescue nil
56
+ return unless time
57
57
 
58
- time -= offset
59
- is_utc? ? time : time.getlocal
60
- else
61
- ::Time.public_send(default_timezone, year, mon, mday, hour, min, sec, microsec) rescue nil
58
+ time -= offset
59
+ is_utc? ? time : time.getlocal
60
+ else
61
+ ::Time.public_send(default_timezone, year, mon, mday, hour, min, sec, microsec) rescue nil
62
+ end
62
63
  end
63
- end
64
64
 
65
- ISO_DATETIME = /\A(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)(\.\d+)?\z/
65
+ ISO_DATETIME = /\A(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)(\.\d+)?\z/
66
66
 
67
- # Doesn't handle time zones.
68
- def fast_string_to_time(string)
69
- if string =~ ISO_DATETIME
70
- microsec = ($7.to_r * 1_000_000).to_i
71
- new_time $1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i, microsec
67
+ # Doesn't handle time zones.
68
+ def fast_string_to_time(string)
69
+ if string =~ ISO_DATETIME
70
+ microsec = ($7.to_r * 1_000_000).to_i
71
+ new_time $1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i, microsec
72
+ end
72
73
  end
73
- end
74
74
  end
75
75
  end
76
76
  end
@@ -16,14 +16,15 @@ module ActiveModel
16
16
 
17
17
  private
18
18
 
19
- def cast_value(value)
20
- result = case value
21
- when true then "t"
22
- when false then "f"
23
- else value.to_s
24
- end
25
- result.freeze
26
- end
19
+ def cast_value(value)
20
+ result = \
21
+ case value
22
+ when true then "t"
23
+ when false then "f"
24
+ else value.to_s
25
+ end
26
+ result.freeze
27
+ end
27
28
  end
28
29
  end
29
30
  end
@@ -29,38 +29,40 @@ module ActiveModel
29
29
  result
30
30
  end
31
31
 
32
+ # TODO Change this to private once we've dropped Ruby 2.2 support.
33
+ # Workaround for Ruby 2.2 "private attribute?" warning.
32
34
  protected
33
35
 
34
- attr_reader :range
36
+ attr_reader :range
35
37
 
36
38
  private
37
39
 
38
- def cast_value(value)
39
- case value
40
- when true then 1
41
- when false then 0
42
- else
43
- value.to_i rescue nil
40
+ def cast_value(value)
41
+ case value
42
+ when true then 1
43
+ when false then 0
44
+ else
45
+ value.to_i rescue nil
46
+ end
44
47
  end
45
- end
46
48
 
47
- def ensure_in_range(value)
48
- unless range.cover?(value)
49
- raise ActiveModel::RangeError, "#{value} is out of range for #{self.class} with limit #{_limit}"
49
+ def ensure_in_range(value)
50
+ unless range.cover?(value)
51
+ raise ActiveModel::RangeError, "#{value} is out of range for #{self.class} with limit #{_limit} bytes"
52
+ end
50
53
  end
51
- end
52
54
 
53
- def max_value
54
- 1 << (_limit * 8 - 1) # 8 bits per byte with one bit for sign
55
- end
55
+ def max_value
56
+ 1 << (_limit * 8 - 1) # 8 bits per byte with one bit for sign
57
+ end
56
58
 
57
- def min_value
58
- -max_value
59
- end
59
+ def min_value
60
+ -max_value
61
+ end
60
62
 
61
- def _limit
62
- self.limit || DEFAULT_LIMIT
63
- end
63
+ def _limit
64
+ limit || DEFAULT_LIMIT
65
+ end
64
66
  end
65
67
  end
66
68
  end
@@ -21,19 +21,21 @@ module ActiveModel
21
21
  end
22
22
  end
23
23
 
24
+ # TODO Change this to private once we've dropped Ruby 2.2 support.
25
+ # Workaround for Ruby 2.2 "private attribute?" warning.
24
26
  protected
25
27
 
26
- attr_reader :registrations
28
+ attr_reader :registrations
27
29
 
28
30
  private
29
31
 
30
- def registration_klass
31
- Registration
32
- end
32
+ def registration_klass
33
+ Registration
34
+ end
33
35
 
34
- def find_registration(symbol, *args)
35
- registrations.find { |r| r.matches?(symbol, *args) }
36
- end
36
+ def find_registration(symbol, *args)
37
+ registrations.find { |r| r.matches?(symbol, *args) }
38
+ end
37
39
  end
38
40
 
39
41
  class Registration
@@ -55,9 +57,11 @@ module ActiveModel
55
57
  type_name == name
56
58
  end
57
59
 
60
+ # TODO Change this to private once we've dropped Ruby 2.2 support.
61
+ # Workaround for Ruby 2.2 "private attribute?" warning.
58
62
  protected
59
63
 
60
- attr_reader :name, :block
64
+ attr_reader :name, :block
61
65
  end
62
66
  end
63
67
  # :startdoc:
@@ -12,12 +12,7 @@ module ActiveModel
12
12
  private
13
13
 
14
14
  def cast_value(value)
15
- case value
16
- when ::String then ::String.new(value)
17
- when true then "t".freeze
18
- when false then "f".freeze
19
- else value.to_s
20
- end
15
+ ::String.new(super)
21
16
  end
22
17
  end
23
18
  end
@@ -25,18 +25,22 @@ module ActiveModel
25
25
 
26
26
  private
27
27
 
28
- def cast_value(value)
29
- return apply_seconds_precision(value) unless value.is_a?(::String)
30
- return if value.empty?
31
-
32
- dummy_time_value = value.sub(/\A(\d\d\d\d-\d\d-\d\d |)/, "2000-01-01 ")
33
-
34
- fast_string_to_time(dummy_time_value) || begin
35
- time_hash = ::Date._parse(dummy_time_value)
36
- return if time_hash[:hour].nil?
37
- new_time(*time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction, :offset))
28
+ def cast_value(value)
29
+ return value unless value.is_a?(::String)
30
+ return if value.empty?
31
+
32
+ if value.start_with?("2000-01-01")
33
+ dummy_time_value = value
34
+ else
35
+ dummy_time_value = "2000-01-01 #{value}"
36
+ end
37
+
38
+ fast_string_to_time(dummy_time_value) || begin
39
+ time_hash = ::Date._parse(dummy_time_value)
40
+ return if time_hash[:hour].nil?
41
+ new_time(*time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction, :offset))
42
+ end
38
43
  end
39
- end
40
44
  end
41
45
  end
42
46
  end
@@ -105,12 +105,12 @@ module ActiveModel
105
105
 
106
106
  private
107
107
 
108
- # Convenience method for types which do not need separate type casting
109
- # behavior for user and database inputs. Called by Value#cast for
110
- # values except +nil+.
111
- def cast_value(value) # :doc:
112
- value
113
- end
108
+ # Convenience method for types which do not need separate type casting
109
+ # behavior for user and database inputs. Called by Value#cast for
110
+ # values except +nil+.
111
+ def cast_value(value) # :doc:
112
+ value
113
+ end
114
114
  end
115
115
  end
116
116
  end
@@ -1,9 +1,8 @@
1
- require 'active_support/core_ext/array/extract_options'
2
- require 'active_support/core_ext/hash/keys'
3
- require 'active_support/core_ext/hash/except'
1
+ require "active_support/core_ext/array/extract_options"
2
+ require "active_support/core_ext/hash/keys"
3
+ require "active_support/core_ext/hash/except"
4
4
 
5
5
  module ActiveModel
6
-
7
6
  # == Active \Model \Validations
8
7
  #
9
8
  # Provides a full validation framework to your objects.
@@ -51,7 +50,7 @@ module ActiveModel
51
50
  define_callbacks :validate, scope: :name
52
51
 
53
52
  class_attribute :_validators, instance_writer: false
54
- self._validators = Hash.new { |h,k| h[k] = [] }
53
+ self._validators = Hash.new { |h, k| h[k] = [] }
55
54
  end
56
55
 
57
56
  module ClassMethods
@@ -69,7 +68,7 @@ module ActiveModel
69
68
  #
70
69
  # Options:
71
70
  # * <tt>:on</tt> - Specifies the contexts where this validation is active.
72
- # Runs in all validation contexts by default (nil). You can pass a symbol
71
+ # Runs in all validation contexts by default +nil+. You can pass a symbol
73
72
  # or an array of symbols. (e.g. <tt>on: :create</tt> or
74
73
  # <tt>on: :custom_validation_context</tt> or
75
74
  # <tt>on: [:create, :custom_validation_context]</tt>)
@@ -135,7 +134,7 @@ module ActiveModel
135
134
  #
136
135
  # Options:
137
136
  # * <tt>:on</tt> - Specifies the contexts where this validation is active.
138
- # Runs in all validation contexts by default (nil). You can pass a symbol
137
+ # Runs in all validation contexts by default +nil+. You can pass a symbol
139
138
  # or an array of symbols. (e.g. <tt>on: :create</tt> or
140
139
  # <tt>on: :custom_validation_context</tt> or
141
140
  # <tt>on: [:create, :custom_validation_context]</tt>)
@@ -304,8 +303,6 @@ module ActiveModel
304
303
  # Runs all the specified validations and returns +true+ if no errors were
305
304
  # added otherwise +false+.
306
305
  #
307
- # Aliased as validate.
308
- #
309
306
  # class Person
310
307
  # include ActiveModel::Validations
311
308
  #
@@ -402,14 +399,14 @@ module ActiveModel
402
399
  # end
403
400
  alias :read_attribute_for_validation :send
404
401
 
405
- protected
402
+ private
406
403
 
407
- def run_validations! #:nodoc:
404
+ def run_validations!
408
405
  _run_validate_callbacks
409
406
  errors.empty?
410
407
  end
411
408
 
412
- def raise_validation_error
409
+ def raise_validation_error # :doc:
413
410
  raise(ValidationError.new(self))
414
411
  end
415
412
  end
@@ -22,7 +22,7 @@ module ActiveModel
22
22
  #
23
23
  # There is also a list of default options supported by every validator:
24
24
  # +:if+, +:unless+, +:on+, +:allow_nil+, +:allow_blank+, and +:strict+.
25
- # See <tt>ActiveModel::Validation#validates</tt> for more information
25
+ # See <tt>ActiveModel::Validations#validates</tt> for more information
26
26
  def validates_absence_of(*attr_names)
27
27
  validates_with AbsenceValidator, _merge_attributes(attr_names)
28
28
  end
@@ -1,5 +1,4 @@
1
1
  module ActiveModel
2
-
3
2
  module Validations
4
3
  class AcceptanceValidator < EachValidator # :nodoc:
5
4
  def initialize(options)
@@ -15,58 +14,60 @@ module ActiveModel
15
14
 
16
15
  private
17
16
 
18
- def setup!(klass)
19
- klass.include(LazilyDefineAttributes.new(AttributeDefinition.new(attributes)))
20
- end
17
+ def setup!(klass)
18
+ klass.include(LazilyDefineAttributes.new(AttributeDefinition.new(attributes)))
19
+ end
21
20
 
22
- def acceptable_option?(value)
23
- Array(options[:accept]).include?(value)
24
- end
21
+ def acceptable_option?(value)
22
+ Array(options[:accept]).include?(value)
23
+ end
25
24
 
26
- class LazilyDefineAttributes < Module
27
- def initialize(attribute_definition)
28
- define_method(:respond_to_missing?) do |method_name, include_private=false|
29
- super(method_name, include_private) || attribute_definition.matches?(method_name)
30
- end
25
+ class LazilyDefineAttributes < Module
26
+ def initialize(attribute_definition)
27
+ define_method(:respond_to_missing?) do |method_name, include_private = false|
28
+ super(method_name, include_private) || attribute_definition.matches?(method_name)
29
+ end
31
30
 
32
- define_method(:method_missing) do |method_name, *args, &block|
33
- if attribute_definition.matches?(method_name)
34
- attribute_definition.define_on(self.class)
35
- send(method_name, *args, &block)
36
- else
37
- super(method_name, *args, &block)
31
+ define_method(:method_missing) do |method_name, *args, &block|
32
+ if attribute_definition.matches?(method_name)
33
+ attribute_definition.define_on(self.class)
34
+ send(method_name, *args, &block)
35
+ else
36
+ super(method_name, *args, &block)
37
+ end
38
38
  end
39
39
  end
40
40
  end
41
- end
42
41
 
43
- class AttributeDefinition
44
- def initialize(attributes)
45
- @attributes = attributes.map(&:to_s)
46
- end
42
+ class AttributeDefinition
43
+ def initialize(attributes)
44
+ @attributes = attributes.map(&:to_s)
45
+ end
47
46
 
48
- def matches?(method_name)
49
- attr_name = convert_to_reader_name(method_name)
50
- attributes.include?(attr_name)
51
- end
47
+ def matches?(method_name)
48
+ attr_name = convert_to_reader_name(method_name)
49
+ attributes.include?(attr_name)
50
+ end
52
51
 
53
- def define_on(klass)
54
- attr_readers = attributes.reject { |name| klass.attribute_method?(name) }
55
- attr_writers = attributes.reject { |name| klass.attribute_method?("#{name}=") }
56
- klass.send(:attr_reader, *attr_readers)
57
- klass.send(:attr_writer, *attr_writers)
58
- end
52
+ def define_on(klass)
53
+ attr_readers = attributes.reject { |name| klass.attribute_method?(name) }
54
+ attr_writers = attributes.reject { |name| klass.attribute_method?("#{name}=") }
55
+ klass.send(:attr_reader, *attr_readers)
56
+ klass.send(:attr_writer, *attr_writers)
57
+ end
59
58
 
60
- protected
59
+ # TODO Change this to private once we've dropped Ruby 2.2 support.
60
+ # Workaround for Ruby 2.2 "private attribute?" warning.
61
+ protected
61
62
 
62
- attr_reader :attributes
63
+ attr_reader :attributes
63
64
 
64
- private
65
+ private
65
66
 
66
- def convert_to_reader_name(method_name)
67
- method_name.to_s.chomp('=')
67
+ def convert_to_reader_name(method_name)
68
+ method_name.to_s.chomp("=")
69
+ end
68
70
  end
69
- end
70
71
  end
71
72
 
72
73
  module HelperMethods
@@ -94,7 +95,7 @@ module ActiveModel
94
95
  #
95
96
  # There is also a list of default options supported by every validator:
96
97
  # +:if+, +:unless+, +:on+, +:allow_nil+, +:allow_blank+, and +:strict+.
97
- # See <tt>ActiveModel::Validation#validates</tt> for more information.
98
+ # See <tt>ActiveModel::Validations#validates</tt> for more information.
98
99
  def validates_acceptance_of(*attr_names)
99
100
  validates_with AcceptanceValidator, _merge_attributes(attr_names)
100
101
  end