activemodel 5.1.7 → 5.2.8.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +126 -40
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +4 -4
  5. data/lib/active_model/attribute/user_provided_default.rb +52 -0
  6. data/lib/active_model/attribute.rb +248 -0
  7. data/lib/active_model/attribute_assignment.rb +10 -5
  8. data/lib/active_model/attribute_methods.rb +12 -10
  9. data/lib/active_model/attribute_mutation_tracker.rb +124 -0
  10. data/lib/active_model/attribute_set/builder.rb +126 -0
  11. data/lib/active_model/attribute_set/yaml_encoder.rb +41 -0
  12. data/lib/active_model/attribute_set.rb +114 -0
  13. data/lib/active_model/attributes.rb +111 -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 +128 -57
  17. data/lib/active_model/errors.rb +31 -20
  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 +14 -12
  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 +3 -1
  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/big_integer.rb +2 -0
  29. data/lib/active_model/type/binary.rb +2 -0
  30. data/lib/active_model/type/boolean.rb +16 -1
  31. data/lib/active_model/type/date.rb +5 -2
  32. data/lib/active_model/type/date_time.rb +7 -0
  33. data/lib/active_model/type/decimal.rb +2 -0
  34. data/lib/active_model/type/float.rb +2 -0
  35. data/lib/active_model/type/helpers/accepts_multiparameter_time.rb +6 -0
  36. data/lib/active_model/type/helpers/mutable.rb +2 -0
  37. data/lib/active_model/type/helpers/numeric.rb +3 -1
  38. data/lib/active_model/type/helpers/time_value.rb +2 -12
  39. data/lib/active_model/type/helpers/timezone.rb +19 -0
  40. data/lib/active_model/type/helpers.rb +3 -0
  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 +7 -0
  46. data/lib/active_model/type/value.rb +6 -0
  47. data/lib/active_model/type.rb +7 -1
  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 +12 -8
  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 +39 -13
  59. data/lib/active_model/validations/presence.rb +1 -0
  60. data/lib/active_model/validations/validates.rb +5 -4
  61. data/lib/active_model/validations/with.rb +2 -0
  62. data/lib/active_model/validations.rb +10 -6
  63. data/lib/active_model/validator.rb +6 -4
  64. data/lib/active_model/version.rb +2 -0
  65. data/lib/active_model.rb +7 -2
  66. metadata +18 -10
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveModel
2
4
  module Type
3
5
  class Float < Value # :nodoc:
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveModel
2
4
  module Type
3
5
  module Helpers # :nodoc: all
@@ -19,6 +21,10 @@ module ActiveModel
19
21
  end
20
22
  end
21
23
 
24
+ define_method(:value_constructed_by_mass_assignment?) do |value|
25
+ value.is_a?(Hash)
26
+ end
27
+
22
28
  define_method(:value_from_multiparameter_assignment) do |values_hash|
23
29
  defaults.each do |k, v|
24
30
  values_hash[k] ||= v
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveModel
2
4
  module Type
3
5
  module Helpers # :nodoc: all
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveModel
2
4
  module Type
3
5
  module Helpers # :nodoc: all
@@ -27,7 +29,7 @@ module ActiveModel
27
29
  # 'wibble'.to_i will give zero, we want to make sure
28
30
  # that we aren't marking int zero to string zero as
29
31
  # changed.
30
- value.to_s !~ /\A-?\d+\.?\d*\z/
32
+ !/\A[-+]?\d+/.match?(value.to_s)
31
33
  end
32
34
  end
33
35
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/string/zones"
2
4
  require "active_support/core_ext/time/zones"
3
5
 
@@ -19,18 +21,6 @@ module ActiveModel
19
21
  value
20
22
  end
21
23
 
22
- def is_utc?
23
- ::Time.zone_default.nil? || ::Time.zone_default =~ "UTC"
24
- end
25
-
26
- def default_timezone
27
- if is_utc?
28
- :utc
29
- else
30
- :local
31
- end
32
- end
33
-
34
24
  def apply_seconds_precision(value)
35
25
  return value unless precision && value.respond_to?(:usec)
36
26
  number_of_insignificant_digits = 6 - precision
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/time/zones"
4
+
5
+ module ActiveModel
6
+ module Type
7
+ module Helpers # :nodoc: all
8
+ module Timezone
9
+ def is_utc?
10
+ ::Time.zone_default.nil? || ::Time.zone_default =~ "UTC"
11
+ end
12
+
13
+ def default_timezone
14
+ is_utc? ? :utc : :local
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -1,4 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_model/type/helpers/accepts_multiparameter_time"
2
4
  require "active_model/type/helpers/numeric"
3
5
  require "active_model/type/helpers/mutable"
4
6
  require "active_model/type/helpers/time_value"
7
+ require "active_model/type/helpers/timezone"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveModel
2
4
  module Type
3
5
  class ImmutableString < Value # :nodoc:
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveModel
2
4
  module Type
3
5
  class Integer < Value # :nodoc:
4
6
  include Helpers::Numeric
5
7
 
6
8
  # Column storage size in bytes.
7
- # 4 bytes means a MySQL int or Postgres integer as opposed to smallint etc.
9
+ # 4 bytes means an integer as opposed to smallint etc.
8
10
  DEFAULT_LIMIT = 4
9
11
 
10
12
  def initialize(*)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveModel
2
4
  # :stopdoc:
3
5
  module Type
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_model/type/immutable_string"
2
4
 
3
5
  module ActiveModel
@@ -1,6 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveModel
2
4
  module Type
3
5
  class Time < Value # :nodoc:
6
+ include Helpers::Timezone
4
7
  include Helpers::TimeValue
5
8
  include Helpers::AcceptsMultiparameterTime.new(
6
9
  defaults: { 1 => 1970, 2 => 1, 3 => 1, 4 => 0, 5 => 0 }
@@ -10,6 +13,10 @@ module ActiveModel
10
13
  :time
11
14
  end
12
15
 
16
+ def serialize(value)
17
+ super(cast(value))
18
+ end
19
+
13
20
  def user_input_in_time_zone(value)
14
21
  return unless value.present?
15
22
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveModel
2
4
  module Type
3
5
  class Value
@@ -84,6 +86,10 @@ module ActiveModel
84
86
  false
85
87
  end
86
88
 
89
+ def value_constructed_by_mass_assignment?(_value) # :nodoc:
90
+ false
91
+ end
92
+
87
93
  def force_equality?(_value) # :nodoc:
88
94
  false
89
95
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_model/type/helpers"
2
4
  require "active_model/type/value"
3
5
 
@@ -22,7 +24,7 @@ module ActiveModel
22
24
  class << self
23
25
  attr_accessor :registry # :nodoc:
24
26
 
25
- # Add a new type to the registry, allowing it to be get through ActiveModel::Type#lookup
27
+ # Add a new type to the registry, allowing it to be gotten through ActiveModel::Type#lookup
26
28
  def register(type_name, klass = nil, **options, &block)
27
29
  registry.register(type_name, klass, **options, &block)
28
30
  end
@@ -30,6 +32,10 @@ module ActiveModel
30
32
  def lookup(*args, **kwargs) # :nodoc:
31
33
  registry.lookup(*args, **kwargs)
32
34
  end
35
+
36
+ def default_value # :nodoc:
37
+ @default_value ||= Value.new
38
+ end
33
39
  end
34
40
 
35
41
  register(:big_integer, Type::BigInteger)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveModel
2
4
  module Validations
3
5
  # == \Active \Model Absence Validator
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveModel
2
4
  module Validations
3
5
  class AcceptanceValidator < EachValidator # :nodoc:
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveModel
2
4
  module Validations
3
5
  # == Active \Model \Validation \Callbacks
@@ -53,16 +55,17 @@ module ActiveModel
53
55
  # person.name # => "bob"
54
56
  def before_validation(*args, &block)
55
57
  options = args.extract_options!
56
- options[:if] = Array(options[:if])
57
58
 
58
59
  if options.key?(:on)
60
+ options = options.dup
61
+ options[:on] = Array(options[:on])
62
+ options[:if] = Array(options[:if])
59
63
  options[:if].unshift ->(o) {
60
- !(Array(options[:on]) & Array(o.validation_context)).empty?
64
+ !(options[:on] & Array(o.validation_context)).empty?
61
65
  }
62
66
  end
63
67
 
64
- args << options
65
- set_callback(:validation, :before, *args, &block)
68
+ set_callback(:validation, :before, *args, options, &block)
66
69
  end
67
70
 
68
71
  # Defines a callback that will get called right after validation.
@@ -93,17 +96,18 @@ module ActiveModel
93
96
  # person.status # => true
94
97
  def after_validation(*args, &block)
95
98
  options = args.extract_options!
99
+ options = options.dup
96
100
  options[:prepend] = true
97
- options[:if] = Array(options[:if])
98
101
 
99
102
  if options.key?(:on)
103
+ options[:on] = Array(options[:on])
104
+ options[:if] = Array(options[:if])
100
105
  options[:if].unshift ->(o) {
101
- !(Array(options[:on]) & Array(o.validation_context)).empty?
106
+ !(options[:on] & Array(o.validation_context)).empty?
102
107
  }
103
108
  end
104
109
 
105
- args << options
106
- set_callback(:validation, :after, *args, &block)
110
+ set_callback(:validation, :after, *args, options, &block)
107
111
  end
108
112
  end
109
113
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/range"
2
4
 
3
5
  module ActiveModel
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveModel
2
4
  module Validations
3
5
  class ConfirmationValidator < EachValidator # :nodoc:
@@ -7,7 +9,7 @@ module ActiveModel
7
9
  end
8
10
 
9
11
  def validate_each(record, attribute, value)
10
- if (confirmed = record.send("#{attribute}_confirmation"))
12
+ unless (confirmed = record.send("#{attribute}_confirmation")).nil?
11
13
  unless confirmation_value_equal?(record, attribute, value, confirmed)
12
14
  human_attribute_name = record.class.human_attribute_name(attribute)
13
15
  record.errors.add(:"#{attribute}_confirmation", :confirmation, options.except(:case_sensitive).merge!(attribute: human_attribute_name))
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_model/validations/clusivity"
2
4
 
3
5
  module ActiveModel
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  module ActiveModel
3
4
  module Validations
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveModel
2
4
  module Validations
3
5
  module HelperMethods # :nodoc:
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_model/validations/clusivity"
2
4
 
3
5
  module ActiveModel
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveModel
2
4
  module Validations
3
5
  class LengthValidator < EachValidator # :nodoc:
@@ -29,8 +31,8 @@ module ActiveModel
29
31
  keys.each do |key|
30
32
  value = options[key]
31
33
 
32
- unless (value.is_a?(Integer) && value >= 0) || value == Float::INFINITY
33
- raise ArgumentError, ":#{key} must be a nonnegative Integer or Infinity"
34
+ unless (value.is_a?(Integer) && value >= 0) || value == Float::INFINITY || value.is_a?(Symbol) || value.is_a?(Proc)
35
+ raise ArgumentError, ":#{key} must be a nonnegative Integer, Infinity, Symbol, or Proc"
34
36
  end
35
37
  end
36
38
  end
@@ -43,6 +45,12 @@ module ActiveModel
43
45
  next unless check_value = options[key]
44
46
 
45
47
  if !value.nil? || skip_nil_check?(key)
48
+ case check_value
49
+ when Proc
50
+ check_value = check_value.call(record)
51
+ when Symbol
52
+ check_value = record.send(check_value)
53
+ end
46
54
  next if value_length.send(validity_check, check_value)
47
55
  end
48
56
 
@@ -1,3 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bigdecimal/util"
4
+
1
5
  module ActiveModel
2
6
  module Validations
3
7
  class NumericalityValidator < EachValidator # :nodoc:
@@ -7,6 +11,8 @@ module ActiveModel
7
11
 
8
12
  RESERVED_OPTIONS = CHECKS.keys + [:only_integer]
9
13
 
14
+ INTEGER_REGEX = /\A[+-]?\d+\z/
15
+
10
16
  def check_validity!
11
17
  keys = CHECKS.keys - [:odd, :even]
12
18
  options.slice(*keys).each do |option, value|
@@ -17,9 +23,20 @@ module ActiveModel
17
23
  end
18
24
 
19
25
  def validate_each(record, attr_name, value)
20
- before_type_cast = :"#{attr_name}_before_type_cast"
26
+ came_from_user = :"#{attr_name}_came_from_user?"
21
27
 
22
- raw_value = record.send(before_type_cast) if record.respond_to?(before_type_cast) && record.send(before_type_cast) != value
28
+ if record.respond_to?(came_from_user)
29
+ if record.public_send(came_from_user)
30
+ raw_value = record.read_attribute_before_type_cast(attr_name)
31
+ elsif record.respond_to?(:read_attribute)
32
+ raw_value = record.read_attribute(attr_name)
33
+ end
34
+ else
35
+ before_type_cast = :"#{attr_name}_before_type_cast"
36
+ if record.respond_to?(before_type_cast)
37
+ raw_value = record.public_send(before_type_cast)
38
+ end
39
+ end
23
40
  raw_value ||= value
24
41
 
25
42
  if record_attribute_changed_in_place?(record, attr_name)
@@ -36,11 +53,7 @@ module ActiveModel
36
53
  return
37
54
  end
38
55
 
39
- if raw_value.is_a?(Numeric)
40
- value = raw_value
41
- else
42
- value = parse_raw_value_as_a_number(raw_value)
43
- end
56
+ value = parse_as_number(raw_value)
44
57
 
45
58
  options.slice(*CHECKS.keys).each do |option, option_value|
46
59
  case option
@@ -56,6 +69,8 @@ module ActiveModel
56
69
  option_value = record.send(option_value)
57
70
  end
58
71
 
72
+ option_value = parse_as_number(option_value)
73
+
59
74
  unless value.send(CHECKS[option], option_value)
60
75
  record.errors.add(attr_name, option, filtered_options(value).merge!(count: option_value))
61
76
  end
@@ -66,18 +81,29 @@ module ActiveModel
66
81
  private
67
82
 
68
83
  def is_number?(raw_value)
69
- !parse_raw_value_as_a_number(raw_value).nil?
84
+ !parse_as_number(raw_value).nil?
70
85
  rescue ArgumentError, TypeError
71
86
  false
72
87
  end
73
88
 
74
- def parse_raw_value_as_a_number(raw_value)
75
- return raw_value.to_i if is_integer?(raw_value)
76
- Kernel.Float(raw_value) if raw_value !~ /\A0[xX]/
89
+ def parse_as_number(raw_value)
90
+ if raw_value.is_a?(Float)
91
+ raw_value.to_d
92
+ elsif raw_value.is_a?(Numeric)
93
+ raw_value
94
+ elsif is_integer?(raw_value)
95
+ raw_value.to_i
96
+ elsif !is_hexadecimal_literal?(raw_value)
97
+ Kernel.Float(raw_value).to_d
98
+ end
77
99
  end
78
100
 
79
101
  def is_integer?(raw_value)
80
- /\A[+-]?\d+\z/ === raw_value.to_s
102
+ INTEGER_REGEX === raw_value.to_s
103
+ end
104
+
105
+ def is_hexadecimal_literal?(raw_value)
106
+ /\A0[xX]/ === raw_value.to_s
81
107
  end
82
108
 
83
109
  def filtered_options(value)
@@ -106,7 +132,7 @@ module ActiveModel
106
132
  module HelperMethods
107
133
  # Validates whether the value of the specified attribute is numeric by
108
134
  # trying to convert it to a float with Kernel.Float (if <tt>only_integer</tt>
109
- # is +false+) or applying it to the regular expression <tt>/\A[\+\-]?\d+\Z/</tt>
135
+ # is +false+) or applying it to the regular expression <tt>/\A[\+\-]?\d+\z/</tt>
110
136
  # (if <tt>only_integer</tt> is set to +true+).
111
137
  #
112
138
  # class Person < ActiveRecord::Base
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  module ActiveModel
3
4
  module Validations
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/hash/slice"
2
4
 
3
5
  module ActiveModel
@@ -18,7 +20,6 @@ module ActiveModel
18
20
  # validates :first_name, length: { maximum: 30 }
19
21
  # validates :age, numericality: true
20
22
  # validates :username, presence: true
21
- # validates :username, uniqueness: true
22
23
  #
23
24
  # The power of the +validates+ method comes when using custom validators
24
25
  # and default validators in one call for a given attribute.
@@ -34,7 +35,7 @@ module ActiveModel
34
35
  # include ActiveModel::Validations
35
36
  # attr_accessor :name, :email
36
37
  #
37
- # validates :name, presence: true, uniqueness: true, length: { maximum: 100 }
38
+ # validates :name, presence: true, length: { maximum: 100 }
38
39
  # validates :email, presence: true, email: true
39
40
  # end
40
41
  #
@@ -94,7 +95,7 @@ module ActiveModel
94
95
  # Example:
95
96
  #
96
97
  # validates :password, presence: true, confirmation: true, if: :password_required?
97
- # validates :token, uniqueness: true, strict: TokenGenerationException
98
+ # validates :token, length: 24, strict: TokenLengthException
98
99
  #
99
100
  #
100
101
  # Finally, the options +:if+, +:unless+, +:on+, +:allow_blank+, +:allow_nil+, +:strict+
@@ -153,7 +154,7 @@ module ActiveModel
153
154
  # When creating custom validators, it might be useful to be able to specify
154
155
  # additional default keys. This can be done by overwriting this method.
155
156
  def _validates_default_keys
156
- [:if, :unless, :on, :allow_blank, :allow_nil , :strict]
157
+ [:if, :unless, :on, :allow_blank, :allow_nil, :strict]
157
158
  end
158
159
 
159
160
  def _parse_validates_options(options)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/array/extract_options"
2
4
 
3
5
  module ActiveModel
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/array/extract_options"
2
4
  require "active_support/core_ext/hash/keys"
3
5
  require "active_support/core_ext/hash/except"
@@ -49,8 +51,7 @@ module ActiveModel
49
51
  private :validation_context=
50
52
  define_callbacks :validate, scope: :name
51
53
 
52
- class_attribute :_validators, instance_writer: false
53
- self._validators = Hash.new { |h, k| h[k] = [] }
54
+ class_attribute :_validators, instance_writer: false, default: Hash.new { |h, k| h[k] = [] }
54
55
  end
55
56
 
56
57
  module ClassMethods
@@ -147,6 +148,9 @@ module ActiveModel
147
148
  # or <tt>unless: Proc.new { |user| user.signup_step <= 2 }</tt>). The
148
149
  # method, proc or string should return or evaluate to a +true+ or +false+
149
150
  # value.
151
+ #
152
+ # NOTE: Calling +validate+ multiple times on the same method will overwrite previous definitions.
153
+ #
150
154
  def validate(*args, &block)
151
155
  options = args.extract_options!
152
156
 
@@ -160,14 +164,14 @@ module ActiveModel
160
164
 
161
165
  if options.key?(:on)
162
166
  options = options.dup
167
+ options[:on] = Array(options[:on])
163
168
  options[:if] = Array(options[:if])
164
169
  options[:if].unshift ->(o) {
165
- !(Array(options[:on]) & Array(o.validation_context)).empty?
170
+ !(options[:on] & Array(o.validation_context)).empty?
166
171
  }
167
172
  end
168
173
 
169
- args << options
170
- set_callback(:validate, *args, &block)
174
+ set_callback(:validate, *args, options, &block)
171
175
  end
172
176
 
173
177
  # List all validators that are being used to validate the model using
@@ -432,4 +436,4 @@ module ActiveModel
432
436
  end
433
437
  end
434
438
 
435
- Dir[File.dirname(__FILE__) + "/validations/*.rb"].each { |file| require file }
439
+ Dir[File.expand_path("validations/*.rb", __dir__)].each { |file| require file }
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/module/anonymous"
2
4
 
3
5
  module ActiveModel
@@ -82,7 +84,7 @@ module ActiveModel
82
84
  # end
83
85
  #
84
86
  # It can be useful to access the class that is using that validator when there are prerequisites such
85
- # as an +attr_accessor+ being present. This class is accessible via +options[:class]+ in the constructor.
87
+ # as an +attr_accessor+ being present. This class is accessible via <tt>options[:class]</tt> in the constructor.
86
88
  # To setup your validator override the constructor.
87
89
  #
88
90
  # class MyValidator < ActiveModel::Validator
@@ -97,7 +99,7 @@ module ActiveModel
97
99
  # Returns the kind of the validator.
98
100
  #
99
101
  # PresenceValidator.kind # => :presence
100
- # UniquenessValidator.kind # => :uniqueness
102
+ # AcceptanceValidator.kind # => :acceptance
101
103
  def self.kind
102
104
  @kind ||= name.split("::").last.underscore.chomp("_validator").to_sym unless anonymous?
103
105
  end
@@ -109,8 +111,8 @@ module ActiveModel
109
111
 
110
112
  # Returns the kind for this validator.
111
113
  #
112
- # PresenceValidator.new.kind # => :presence
113
- # UniquenessValidator.new.kind # => :uniqueness
114
+ # PresenceValidator.new(attributes: [:username]).kind # => :presence
115
+ # AcceptanceValidator.new(attributes: [:terms]).kind # => :acceptance
114
116
  def kind
115
117
  self.class.kind
116
118
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative "gem_version"
2
4
 
3
5
  module ActiveModel
data/lib/active_model.rb CHANGED
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  #--
2
- # Copyright (c) 2004-2017 David Heinemeier Hansson
4
+ # Copyright (c) 2004-2018 David Heinemeier Hansson
3
5
  #
4
6
  # Permission is hereby granted, free of charge, to any person obtaining
5
7
  # a copy of this software and associated documentation files (the
@@ -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