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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +15 -219
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/lib/active_model.rb +11 -12
- data/lib/active_model/attribute_assignment.rb +11 -11
- data/lib/active_model/attribute_methods.rb +13 -15
- data/lib/active_model/callbacks.rb +19 -20
- data/lib/active_model/conversion.rb +12 -3
- data/lib/active_model/dirty.rb +14 -14
- data/lib/active_model/errors.rb +27 -103
- data/lib/active_model/forbidden_attributes_protection.rb +1 -1
- data/lib/active_model/gem_version.rb +3 -3
- data/lib/active_model/lint.rb +0 -1
- data/lib/active_model/model.rb +3 -4
- data/lib/active_model/naming.rb +9 -10
- data/lib/active_model/secure_password.rb +1 -1
- data/lib/active_model/serialization.rb +2 -2
- data/lib/active_model/serializers/json.rb +2 -2
- data/lib/active_model/translation.rb +2 -3
- data/lib/active_model/type.rb +15 -19
- data/lib/active_model/type/big_integer.rb +4 -4
- data/lib/active_model/type/binary.rb +1 -1
- data/lib/active_model/type/boolean.rb +20 -9
- data/lib/active_model/type/date.rb +25 -25
- data/lib/active_model/type/date_time.rb +21 -21
- data/lib/active_model/type/decimal.rb +35 -39
- data/lib/active_model/type/float.rb +17 -8
- data/lib/active_model/type/helpers.rb +4 -4
- data/lib/active_model/type/helpers/accepts_multiparameter_time.rb +2 -2
- data/lib/active_model/type/helpers/mutable.rb +2 -2
- data/lib/active_model/type/helpers/numeric.rb +18 -17
- data/lib/active_model/type/helpers/time_value.rb +23 -23
- data/lib/active_model/type/immutable_string.rb +9 -8
- data/lib/active_model/type/integer.rb +23 -21
- data/lib/active_model/type/registry.rb +12 -8
- data/lib/active_model/type/string.rb +1 -6
- data/lib/active_model/type/time.rb +15 -11
- data/lib/active_model/type/value.rb +6 -6
- data/lib/active_model/validations.rb +9 -12
- data/lib/active_model/validations/absence.rb +1 -1
- data/lib/active_model/validations/acceptance.rb +41 -40
- data/lib/active_model/validations/callbacks.rb +4 -7
- data/lib/active_model/validations/clusivity.rb +7 -7
- data/lib/active_model/validations/confirmation.rb +15 -16
- data/lib/active_model/validations/exclusion.rb +1 -2
- data/lib/active_model/validations/format.rb +24 -24
- data/lib/active_model/validations/inclusion.rb +1 -2
- data/lib/active_model/validations/length.rb +6 -42
- data/lib/active_model/validations/numericality.rb +3 -11
- data/lib/active_model/validations/presence.rb +1 -2
- data/lib/active_model/validations/validates.rb +6 -6
- data/lib/active_model/validations/with.rb +4 -2
- data/lib/active_model/validator.rb +5 -6
- data/lib/active_model/version.rb +1 -1
- metadata +8 -11
- data/lib/active_model/test_case.rb +0 -4
- data/lib/active_model/type/decimal_without_scale.rb +0 -11
- data/lib/active_model/type/text.rb +0 -11
- data/lib/active_model/type/unsigned_integer.rb +0 -15
@@ -55,7 +55,7 @@ module ActiveModel
|
|
55
55
|
# This is to avoid ActiveModel (and by extension the entire framework)
|
56
56
|
# being dependent on a binary library.
|
57
57
|
begin
|
58
|
-
require
|
58
|
+
require "bcrypt"
|
59
59
|
rescue LoadError
|
60
60
|
$stderr.puts "You don't have bcrypt installed in your application. Please add it to your Gemfile and run bundle install"
|
61
61
|
raise
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "active_support/json"
|
2
2
|
|
3
3
|
module ActiveModel
|
4
4
|
module Serializers
|
@@ -134,7 +134,7 @@ module ActiveModel
|
|
134
134
|
# person.name # => "bob"
|
135
135
|
# person.age # => 22
|
136
136
|
# person.awesome # => true
|
137
|
-
def from_json(json, include_root=include_root_in_json)
|
137
|
+
def from_json(json, include_root = include_root_in_json)
|
138
138
|
hash = ActiveSupport::JSON.decode(json)
|
139
139
|
hash = hash.values.first if include_root
|
140
140
|
self.attributes = hash
|
@@ -1,5 +1,4 @@
|
|
1
1
|
module ActiveModel
|
2
|
-
|
3
2
|
# == Active \Model \Translation
|
4
3
|
#
|
5
4
|
# Provides integration between your object and the Rails internationalization
|
@@ -31,7 +30,7 @@ module ActiveModel
|
|
31
30
|
# ActiveModel::Errors#full_messages and
|
32
31
|
# ActiveModel::Translation#human_attribute_name.
|
33
32
|
def lookup_ancestors
|
34
|
-
|
33
|
+
ancestors.select { |x| x.respond_to?(:model_name) }
|
35
34
|
end
|
36
35
|
|
37
36
|
# Transforms attribute names into a more human format, such as "First name"
|
@@ -45,7 +44,7 @@ module ActiveModel
|
|
45
44
|
parts = attribute.to_s.split(".")
|
46
45
|
attribute = parts.pop
|
47
46
|
namespace = parts.join("/") unless parts.empty?
|
48
|
-
attributes_scope = "#{
|
47
|
+
attributes_scope = "#{i18n_scope}.attributes"
|
49
48
|
|
50
49
|
if namespace
|
51
50
|
defaults = lookup_ancestors.map do |klass|
|
data/lib/active_model/type.rb
CHANGED
@@ -1,22 +1,19 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "active_model/type/helpers"
|
2
|
+
require "active_model/type/value"
|
3
3
|
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
11
|
-
require
|
12
|
-
require
|
13
|
-
require
|
14
|
-
require
|
15
|
-
require 'active_model/type/text'
|
16
|
-
require 'active_model/type/time'
|
17
|
-
require 'active_model/type/unsigned_integer'
|
4
|
+
require "active_model/type/big_integer"
|
5
|
+
require "active_model/type/binary"
|
6
|
+
require "active_model/type/boolean"
|
7
|
+
require "active_model/type/date"
|
8
|
+
require "active_model/type/date_time"
|
9
|
+
require "active_model/type/decimal"
|
10
|
+
require "active_model/type/float"
|
11
|
+
require "active_model/type/immutable_string"
|
12
|
+
require "active_model/type/integer"
|
13
|
+
require "active_model/type/string"
|
14
|
+
require "active_model/type/time"
|
18
15
|
|
19
|
-
require
|
16
|
+
require "active_model/type/registry"
|
20
17
|
|
21
18
|
module ActiveModel
|
22
19
|
module Type
|
@@ -27,7 +24,7 @@ module ActiveModel
|
|
27
24
|
delegate :add_modifier, to: :registry
|
28
25
|
|
29
26
|
# Add a new type to the registry, allowing it to be referenced as a
|
30
|
-
# symbol by
|
27
|
+
# symbol by ActiveRecord::Attributes::ClassMethods#attribute. If your
|
31
28
|
# type is only meant to be used with a specific database adapter, you can
|
32
29
|
# do so by passing +adapter: :postgresql+. If your type has the same
|
33
30
|
# name as a native type for the current adapter, an exception will be
|
@@ -53,7 +50,6 @@ module ActiveModel
|
|
53
50
|
register(:immutable_string, Type::ImmutableString)
|
54
51
|
register(:integer, Type::Integer)
|
55
52
|
register(:string, Type::String)
|
56
|
-
register(:text, Type::Text)
|
57
53
|
register(:time, Type::Time)
|
58
54
|
end
|
59
55
|
end
|
@@ -1,13 +1,13 @@
|
|
1
|
-
require
|
1
|
+
require "active_model/type/integer"
|
2
2
|
|
3
3
|
module ActiveModel
|
4
4
|
module Type
|
5
5
|
class BigInteger < Integer # :nodoc:
|
6
6
|
private
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
def max_value
|
9
|
+
::Float::INFINITY
|
10
|
+
end
|
11
11
|
end
|
12
12
|
end
|
13
13
|
end
|
@@ -1,21 +1,32 @@
|
|
1
1
|
module ActiveModel
|
2
2
|
module Type
|
3
|
-
|
4
|
-
|
3
|
+
# == Active \Model \Type \Boolean
|
4
|
+
#
|
5
|
+
# A class that behaves like a boolean type, including rules for coercion of user input.
|
6
|
+
#
|
7
|
+
# === Coercion
|
8
|
+
# Values set from user input will first be coerced into the appropriate ruby type.
|
9
|
+
# Coercion behavior is roughly mapped to Ruby's boolean semantics.
|
10
|
+
#
|
11
|
+
# - "false", "f" , "0", +0+ or any other value in +FALSE_VALUES+ will be coerced to +false+
|
12
|
+
# - Empty strings are coerced to +nil+
|
13
|
+
# - All other values will be coerced to +true+
|
14
|
+
class Boolean < Value
|
15
|
+
FALSE_VALUES = [false, 0, "0", "f", "F", "false", "FALSE", "off", "OFF"].to_set
|
5
16
|
|
6
|
-
def type
|
17
|
+
def type # :nodoc:
|
7
18
|
:boolean
|
8
19
|
end
|
9
20
|
|
10
21
|
private
|
11
22
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
23
|
+
def cast_value(value)
|
24
|
+
if value == ""
|
25
|
+
nil
|
26
|
+
else
|
27
|
+
!FALSE_VALUES.include?(value)
|
28
|
+
end
|
17
29
|
end
|
18
|
-
end
|
19
30
|
end
|
20
31
|
end
|
21
32
|
end
|
@@ -17,38 +17,38 @@ module ActiveModel
|
|
17
17
|
|
18
18
|
private
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
20
|
+
def cast_value(value)
|
21
|
+
if value.is_a?(::String)
|
22
|
+
return if value.empty?
|
23
|
+
fast_string_to_date(value) || fallback_string_to_date(value)
|
24
|
+
elsif value.respond_to?(:to_date)
|
25
|
+
value.to_date
|
26
|
+
else
|
27
|
+
value
|
28
|
+
end
|
28
29
|
end
|
29
|
-
end
|
30
30
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
31
|
+
ISO_DATE = /\A(\d{4})-(\d\d)-(\d\d)\z/
|
32
|
+
def fast_string_to_date(string)
|
33
|
+
if string =~ ISO_DATE
|
34
|
+
new_date $1.to_i, $2.to_i, $3.to_i
|
35
|
+
end
|
35
36
|
end
|
36
|
-
end
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
|
38
|
+
def fallback_string_to_date(string)
|
39
|
+
new_date(*::Date._parse(string, false).values_at(:year, :mon, :mday))
|
40
|
+
end
|
41
41
|
|
42
|
-
|
43
|
-
|
44
|
-
|
42
|
+
def new_date(year, mon, mday)
|
43
|
+
if year && year != 0
|
44
|
+
::Date.new(year, mon, mday) rescue nil
|
45
|
+
end
|
45
46
|
end
|
46
|
-
end
|
47
47
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
48
|
+
def value_from_multiparameter_assignment(*)
|
49
|
+
time = super
|
50
|
+
time && time.to_date
|
51
|
+
end
|
52
52
|
end
|
53
53
|
end
|
54
54
|
end
|
@@ -12,33 +12,33 @@ module ActiveModel
|
|
12
12
|
|
13
13
|
private
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
def cast_value(value)
|
16
|
+
return apply_seconds_precision(value) unless value.is_a?(::String)
|
17
|
+
return if value.empty?
|
18
18
|
|
19
|
-
|
20
|
-
|
19
|
+
fast_string_to_time(value) || fallback_string_to_time(value)
|
20
|
+
end
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
22
|
+
# '0.123456' -> 123456
|
23
|
+
# '1.123456' -> 123456
|
24
|
+
def microseconds(time)
|
25
|
+
time[:sec_fraction] ? (time[:sec_fraction] * 1_000_000).to_i : 0
|
26
|
+
end
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
def fallback_string_to_time(string)
|
29
|
+
time_hash = ::Date._parse(string)
|
30
|
+
time_hash[:sec_fraction] = microseconds(time_hash)
|
31
31
|
|
32
|
-
|
33
|
-
|
32
|
+
new_time(*time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction, :offset))
|
33
|
+
end
|
34
34
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
35
|
+
def value_from_multiparameter_assignment(values_hash)
|
36
|
+
missing_parameter = (1..3).detect { |key| !values_hash.key?(key) }
|
37
|
+
if missing_parameter
|
38
|
+
raise ArgumentError, missing_parameter
|
39
|
+
end
|
40
|
+
super
|
39
41
|
end
|
40
|
-
super
|
41
|
-
end
|
42
42
|
end
|
43
43
|
end
|
44
44
|
end
|
@@ -4,6 +4,7 @@ module ActiveModel
|
|
4
4
|
module Type
|
5
5
|
class Decimal < Value # :nodoc:
|
6
6
|
include Helpers::Numeric
|
7
|
+
BIGDECIMAL_PRECISION = 18
|
7
8
|
|
8
9
|
def type
|
9
10
|
:decimal
|
@@ -15,52 +16,47 @@ module ActiveModel
|
|
15
16
|
|
16
17
|
private
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
cast_value(value.to_s)
|
35
|
-
end
|
19
|
+
def cast_value(value)
|
20
|
+
casted_value = \
|
21
|
+
case value
|
22
|
+
when ::Float
|
23
|
+
convert_float_to_big_decimal(value)
|
24
|
+
when ::Numeric, ::String
|
25
|
+
BigDecimal(value, precision || BIGDECIMAL_PRECISION)
|
26
|
+
else
|
27
|
+
if value.respond_to?(:to_d)
|
28
|
+
value.to_d
|
29
|
+
else
|
30
|
+
cast_value(value.to_s)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
apply_scale(casted_value)
|
36
35
|
end
|
37
36
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
else
|
45
|
-
value.to_d
|
37
|
+
def convert_float_to_big_decimal(value)
|
38
|
+
if precision
|
39
|
+
BigDecimal(apply_scale(value), float_precision)
|
40
|
+
else
|
41
|
+
value.to_d
|
42
|
+
end
|
46
43
|
end
|
47
|
-
end
|
48
44
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
45
|
+
def float_precision
|
46
|
+
if precision.to_i > ::Float::DIG + 1
|
47
|
+
::Float::DIG + 1
|
48
|
+
else
|
49
|
+
precision.to_i
|
50
|
+
end
|
54
51
|
end
|
55
|
-
end
|
56
52
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
53
|
+
def apply_scale(value)
|
54
|
+
if scale
|
55
|
+
value.round(scale)
|
56
|
+
else
|
57
|
+
value
|
58
|
+
end
|
62
59
|
end
|
63
|
-
end
|
64
60
|
end
|
65
61
|
end
|
66
62
|
end
|
@@ -7,19 +7,28 @@ module ActiveModel
|
|
7
7
|
:float
|
8
8
|
end
|
9
9
|
|
10
|
+
def type_cast_for_schema(value)
|
11
|
+
return "::Float::NAN" if value.try(:nan?)
|
12
|
+
case value
|
13
|
+
when ::Float::INFINITY then "::Float::INFINITY"
|
14
|
+
when -::Float::INFINITY then "-::Float::INFINITY"
|
15
|
+
else super
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
10
19
|
alias serialize cast
|
11
20
|
|
12
21
|
private
|
13
22
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
23
|
+
def cast_value(value)
|
24
|
+
case value
|
25
|
+
when ::Float then value
|
26
|
+
when "Infinity" then ::Float::INFINITY
|
27
|
+
when "-Infinity" then -::Float::INFINITY
|
28
|
+
when "NaN" then ::Float::NAN
|
29
|
+
else value.to_f
|
30
|
+
end
|
21
31
|
end
|
22
|
-
end
|
23
32
|
end
|
24
33
|
end
|
25
34
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
1
|
+
require "active_model/type/helpers/accepts_multiparameter_time"
|
2
|
+
require "active_model/type/helpers/numeric"
|
3
|
+
require "active_model/type/helpers/mutable"
|
4
|
+
require "active_model/type/helpers/time_value"
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module ActiveModel
|
2
2
|
module Type
|
3
|
-
module Helpers
|
4
|
-
class AcceptsMultiparameterTime < Module
|
3
|
+
module Helpers # :nodoc: all
|
4
|
+
class AcceptsMultiparameterTime < Module
|
5
5
|
def initialize(defaults: {})
|
6
6
|
define_method(:cast) do |value|
|
7
7
|
if value.is_a?(Hash)
|