aboutsummaryrefslogtreecommitdiffstats
path: root/activemodel
diff options
context:
space:
mode:
Diffstat (limited to 'activemodel')
-rw-r--r--activemodel/CHANGELOG.md5
-rw-r--r--activemodel/activemodel.gemspec2
-rw-r--r--activemodel/lib/active_model/errors.rb5
-rw-r--r--activemodel/lib/active_model/type.rb2
-rw-r--r--activemodel/lib/active_model/type/decimal.rb12
-rw-r--r--activemodel/lib/active_model/validations/clusivity.rb7
-rw-r--r--activemodel/test/cases/errors_test.rb7
-rw-r--r--activemodel/test/cases/type/decimal_test.rb7
-rw-r--r--activemodel/test/cases/validations/inclusion_validation_test.rb20
-rw-r--r--activemodel/test/cases/validations_test.rb16
10 files changed, 71 insertions, 12 deletions
diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md
index fb7ab5cb40..7be8b2e522 100644
--- a/activemodel/CHANGELOG.md
+++ b/activemodel/CHANGELOG.md
@@ -1,3 +1,8 @@
+* Allow passing record being validated to the message proc to generate
+ customized error messages for that object using I18n helper.
+
+ *Prathamesh Sonpatki*
+
## Rails 5.0.0.beta3 (February 24, 2016) ##
* No changes.
diff --git a/activemodel/activemodel.gemspec b/activemodel/activemodel.gemspec
index 53206580f0..1c3997b864 100644
--- a/activemodel/activemodel.gemspec
+++ b/activemodel/activemodel.gemspec
@@ -13,7 +13,7 @@ Gem::Specification.new do |s|
s.author = 'David Heinemeier Hansson'
s.email = 'david@loudthinking.com'
- s.homepage = 'http://www.rubyonrails.org'
+ s.homepage = 'http://rubyonrails.org'
s.files = Dir['CHANGELOG.md', 'MIT-LICENSE', 'README.rdoc', 'lib/**/*']
s.require_path = 'lib'
diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb
index 36834bbd36..d925960b41 100644
--- a/activemodel/lib/active_model/errors.rb
+++ b/activemodel/lib/active_model/errors.rb
@@ -110,7 +110,7 @@ module ActiveModel
# person.errors.include?(:name) # => true
# person.errors.include?(:age) # => false
def include?(attribute)
- messages[attribute].present?
+ messages.key?(attribute) && messages[attribute].present?
end
alias :has_key? :include?
alias :key? :include?
@@ -486,7 +486,8 @@ module ActiveModel
default: defaults,
model: @base.model_name.human,
attribute: @base.class.human_attribute_name(attribute),
- value: value
+ value: value,
+ object: @base
}.merge!(options)
I18n.translate(key, options)
diff --git a/activemodel/lib/active_model/type.rb b/activemodel/lib/active_model/type.rb
index bec851594f..6ec3452478 100644
--- a/activemodel/lib/active_model/type.rb
+++ b/activemodel/lib/active_model/type.rb
@@ -47,7 +47,7 @@ module ActiveModel
register(:binary, Type::Binary)
register(:boolean, Type::Boolean)
register(:date, Type::Date)
- register(:date_time, Type::DateTime)
+ register(:datetime, Type::DateTime)
register(:decimal, Type::Decimal)
register(:float, Type::Float)
register(:immutable_string, Type::ImmutableString)
diff --git a/activemodel/lib/active_model/type/decimal.rb b/activemodel/lib/active_model/type/decimal.rb
index d19d8baada..11ea327026 100644
--- a/activemodel/lib/active_model/type/decimal.rb
+++ b/activemodel/lib/active_model/type/decimal.rb
@@ -29,12 +29,12 @@ module ActiveModel
end
end
- scale ? casted_value.round(scale) : casted_value
+ apply_scale(casted_value)
end
def convert_float_to_big_decimal(value)
if precision
- BigDecimal(value, float_precision)
+ BigDecimal(apply_scale(value), float_precision)
else
value.to_d
end
@@ -47,6 +47,14 @@ module ActiveModel
precision.to_i
end
end
+
+ def apply_scale(value)
+ if scale
+ value.round(scale)
+ else
+ value
+ end
+ end
end
end
end
diff --git a/activemodel/lib/active_model/validations/clusivity.rb b/activemodel/lib/active_model/validations/clusivity.rb
index bad9e4f9a9..d49af603bb 100644
--- a/activemodel/lib/active_model/validations/clusivity.rb
+++ b/activemodel/lib/active_model/validations/clusivity.rb
@@ -30,14 +30,15 @@ module ActiveModel
@delimiter ||= options[:in] || options[:within]
end
- # In Ruby 1.9 <tt>Range#include?</tt> on non-number-or-time-ish ranges checks all
+ # In Ruby 2.2 <tt>Range#include?</tt> on non-number-or-time-ish ranges checks all
# possible values in the range for equality, which is slower but more accurate.
# <tt>Range#cover?</tt> uses the previous logic of comparing a value with the range
- # endpoints, which is fast but is only accurate on Numeric, Time, or DateTime ranges.
+ # endpoints, which is fast but is only accurate on Numeric, Time, Date,
+ # or DateTime ranges.
def inclusion_method(enumerable)
if enumerable.is_a? Range
case enumerable.first
- when Numeric, Time, DateTime
+ when Numeric, Time, DateTime, Date
:cover?
else
:include?
diff --git a/activemodel/test/cases/errors_test.rb b/activemodel/test/cases/errors_test.rb
index a5ac055033..26ba6ba4fb 100644
--- a/activemodel/test/cases/errors_test.rb
+++ b/activemodel/test/cases/errors_test.rb
@@ -128,6 +128,13 @@ class ErrorsTest < ActiveModel::TestCase
assert !person.errors.include?(:foo)
end
+ test "include? does not add a key to messages hash" do
+ person = Person.new
+ person.errors.include?(:foo)
+
+ assert_not person.errors.messages.key?(:foo)
+ end
+
test "adding errors using conditionals with Person#validate!" do
person = Person.new
person.validate!
diff --git a/activemodel/test/cases/type/decimal_test.rb b/activemodel/test/cases/type/decimal_test.rb
index 353dbf84ad..1950566c0e 100644
--- a/activemodel/test/cases/type/decimal_test.rb
+++ b/activemodel/test/cases/type/decimal_test.rb
@@ -52,6 +52,13 @@ module ActiveModel
assert_not type.changed?(5.0, 5.0, '5.0')
assert_not type.changed?(-5.0, -5.0, '-5.0')
end
+
+ def test_scale_is_applied_before_precision_to_prevent_rounding_errors
+ type = Decimal.new(precision: 5, scale: 3)
+
+ assert_equal BigDecimal("1.250"), type.cast(1.250473853637869)
+ assert_equal BigDecimal("1.250"), type.cast("1.250473853637869")
+ end
end
end
end
diff --git a/activemodel/test/cases/validations/inclusion_validation_test.rb b/activemodel/test/cases/validations/inclusion_validation_test.rb
index 6cb96343fa..9bd44175a6 100644
--- a/activemodel/test/cases/validations/inclusion_validation_test.rb
+++ b/activemodel/test/cases/validations/inclusion_validation_test.rb
@@ -21,24 +21,38 @@ class InclusionValidationTest < ActiveModel::TestCase
end
def test_validates_inclusion_of_time_range
- Topic.validates_inclusion_of(:created_at, in: 1.year.ago..Time.now)
+ range_begin = 1.year.ago
+ range_end = Time.now
+ Topic.validates_inclusion_of(:created_at, in: range_begin..range_end)
assert Topic.new(title: 'aaa', created_at: 2.years.ago).invalid?
assert Topic.new(title: 'aaa', created_at: 3.months.ago).valid?
assert Topic.new(title: 'aaa', created_at: 37.weeks.from_now).invalid?
+ assert Topic.new(title: 'aaa', created_at: range_begin).valid?
+ assert Topic.new(title: 'aaa', created_at: range_end).valid?
end
def test_validates_inclusion_of_date_range
- Topic.validates_inclusion_of(:created_at, in: 1.year.until(Date.today)..Date.today)
+ range_begin = 1.year.until(Date.today)
+ range_end = Date.today
+ Topic.validates_inclusion_of(:created_at, in: range_begin..range_end)
assert Topic.new(title: 'aaa', created_at: 2.years.until(Date.today)).invalid?
assert Topic.new(title: 'aaa', created_at: 3.months.until(Date.today)).valid?
assert Topic.new(title: 'aaa', created_at: 37.weeks.since(Date.today)).invalid?
+ assert Topic.new(title: 'aaa', created_at: 1.year.until(Date.today)).valid?
+ assert Topic.new(title: 'aaa', created_at: Date.today).valid?
+ assert Topic.new(title: 'aaa', created_at: range_begin).valid?
+ assert Topic.new(title: 'aaa', created_at: range_end).valid?
end
def test_validates_inclusion_of_date_time_range
- Topic.validates_inclusion_of(:created_at, in: 1.year.until(DateTime.current)..DateTime.current)
+ range_begin = 1.year.until(DateTime.current)
+ range_end = DateTime.current
+ Topic.validates_inclusion_of(:created_at, in: range_begin..range_end)
assert Topic.new(title: 'aaa', created_at: 2.years.until(DateTime.current)).invalid?
assert Topic.new(title: 'aaa', created_at: 3.months.until(DateTime.current)).valid?
assert Topic.new(title: 'aaa', created_at: 37.weeks.since(DateTime.current)).invalid?
+ assert Topic.new(title: 'aaa', created_at: range_begin).valid?
+ assert Topic.new(title: 'aaa', created_at: range_end).valid?
end
def test_validates_inclusion_of
diff --git a/activemodel/test/cases/validations_test.rb b/activemodel/test/cases/validations_test.rb
index f0317ad219..2a4e9f842f 100644
--- a/activemodel/test/cases/validations_test.rb
+++ b/activemodel/test/cases/validations_test.rb
@@ -444,4 +444,20 @@ class ValidationsTest < ActiveModel::TestCase
assert topic.invalid?
assert duped.valid?
end
+
+ def test_validation_with_message_as_proc_that_takes_a_record_as_a_parameter
+ Topic.validates_presence_of(:title, message: proc { |record| "You have failed me for the last time, #{record.author_name}." })
+
+ t = Topic.new(author_name: 'Admiral')
+ assert t.invalid?
+ assert_equal ["You have failed me for the last time, Admiral."], t.errors[:title]
+ end
+
+ def test_validation_with_message_as_proc_that_takes_record_and_data_as_a_parameters
+ Topic.validates_presence_of(:title, message: proc { |record, data| "#{data[:attribute]} is missing. You have failed me for the last time, #{record.author_name}." })
+
+ t = Topic.new(author_name: 'Admiral')
+ assert t.invalid?
+ assert_equal ["Title is missing. You have failed me for the last time, Admiral."], t.errors[:title]
+ end
end