activemodel 5.0.7.2 → 5.1.0.beta1

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