From 7308991630af3fb8a2a7e2cde9fd322316153ec2 Mon Sep 17 00:00:00 2001
From: bogdanvlviv <bogdanvlviv@gmail.com>
Date: Sun, 5 Nov 2017 19:19:41 +0000
Subject: Execute `ConfirmationValidator` validation when `_confirmation`'s
 value is `false`

---
 activemodel/CHANGELOG.md                                    |  4 ++++
 activemodel/lib/active_model/validations/confirmation.rb    |  2 +-
 .../test/cases/validations/confirmation_validation_test.rb  | 13 +++++++++++++
 3 files changed, 18 insertions(+), 1 deletion(-)

(limited to 'activemodel')

diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md
index 82e3a7f4dd..794744c646 100644
--- a/activemodel/CHANGELOG.md
+++ b/activemodel/CHANGELOG.md
@@ -1,3 +1,7 @@
+*   Execute `ConfirmationValidator` validation when `_confirmation`'s value is `false`.
+
+    *bogdanvlviv*
+
 *   Allow passing a Proc or Symbol to length validator options.
 
     *Matt Rohrer*
diff --git a/activemodel/lib/active_model/validations/confirmation.rb b/activemodel/lib/active_model/validations/confirmation.rb
index 0abec56b68..1b5d5b09ab 100644
--- a/activemodel/lib/active_model/validations/confirmation.rb
+++ b/activemodel/lib/active_model/validations/confirmation.rb
@@ -9,7 +9,7 @@ module ActiveModel
       end
 
       def validate_each(record, attribute, value)
-        if (confirmed = record.send("#{attribute}_confirmation"))
+        unless (confirmed = record.send("#{attribute}_confirmation")).nil?
           unless confirmation_value_equal?(record, attribute, value, confirmed)
             human_attribute_name = record.class.human_attribute_name(attribute)
             record.errors.add(:"#{attribute}_confirmation", :confirmation, options.except(:case_sensitive).merge!(attribute: human_attribute_name))
diff --git a/activemodel/test/cases/validations/confirmation_validation_test.rb b/activemodel/test/cases/validations/confirmation_validation_test.rb
index e84415a868..8b2c65289b 100644
--- a/activemodel/test/cases/validations/confirmation_validation_test.rb
+++ b/activemodel/test/cases/validations/confirmation_validation_test.rb
@@ -37,6 +37,19 @@ class ConfirmationValidationTest < ActiveModel::TestCase
     assert t.valid?
   end
 
+  def test_validates_confirmation_of_with_boolean_attribute
+    Topic.validates_confirmation_of(:approved)
+
+    t = Topic.new(approved: true, approved_confirmation: nil)
+    assert t.valid?
+
+    t.approved_confirmation = false
+    assert t.invalid?
+
+    t.approved_confirmation = true
+    assert t.valid?
+  end
+
   def test_validates_confirmation_of_for_ruby_class
     Person.validates_confirmation_of :karma
 
-- 
cgit v1.2.3


From 3ff2c158372bce45ea46bd3b49c49022a4259aba Mon Sep 17 00:00:00 2001
From: bogdanvlviv <bogdanvlviv@gmail.com>
Date: Sun, 5 Nov 2017 22:25:37 +0000
Subject: Add cases to test combining validation conditions

 - Test condition that is defined by array of conditions
 - Test condition that is defined by combining :if and :unless
 - Test local condition that is defined by :if
 - Test local condition that is defined by :unless

See http://edgeguides.rubyonrails.org/active_record_validations.html#combining-validation-conditions
---
 .../validations/conditional_validation_test.rb     | 49 +++++++++++++++++++++-
 .../validations/numericality_validation_test.rb    |  2 +-
 .../test/cases/validations/validates_test.rb       | 12 ++++--
 activemodel/test/models/person.rb                  |  4 ++
 activemodel/test/models/topic.rb                   |  2 +-
 5 files changed, 62 insertions(+), 7 deletions(-)

(limited to 'activemodel')

diff --git a/activemodel/test/cases/validations/conditional_validation_test.rb b/activemodel/test/cases/validations/conditional_validation_test.rb
index aa027c4128..caea8b65ef 100644
--- a/activemodel/test/cases/validations/conditional_validation_test.rb
+++ b/activemodel/test/cases/validations/conditional_validation_test.rb
@@ -18,6 +18,22 @@ class ConditionalValidationTest < ActiveModel::TestCase
     assert_equal ["hoo 5"], t.errors["title"]
   end
 
+  def test_if_validation_using_array_of_true_methods
+    Topic.validates_length_of(:title, maximum: 5, too_long: "hoo %{count}", if: [:condition_is_true, :condition_is_true])
+    t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
+    assert t.invalid?
+    assert t.errors[:title].any?
+    assert_equal ["hoo 5"], t.errors["title"]
+  end
+
+  def test_unless_validation_using_array_of_false_methods
+    Topic.validates_length_of(:title, maximum: 5, too_long: "hoo %{count}", unless: [:condition_is_false, :condition_is_false])
+    t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
+    assert t.invalid?
+    assert t.errors[:title].any?
+    assert_equal ["hoo 5"], t.errors["title"]
+  end
+
   def test_unless_validation_using_method_true
     # When the method returns true
     Topic.validates_length_of(:title, maximum: 5, too_long: "hoo %{count}", unless: :condition_is_true)
@@ -26,9 +42,23 @@ class ConditionalValidationTest < ActiveModel::TestCase
     assert_empty t.errors[:title]
   end
 
+  def test_if_validation_using_array_of_true_and_false_methods
+    Topic.validates_length_of(:title, maximum: 5, too_long: "hoo %{count}", if: [:condition_is_true, :condition_is_false])
+    t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
+    assert t.valid?
+    assert_empty t.errors[:title]
+  end
+
+  def test_unless_validation_using_array_of_true_and_felse_methods
+    Topic.validates_length_of(:title, maximum: 5, too_long: "hoo %{count}", unless: [:condition_is_true, :condition_is_false])
+    t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
+    assert t.valid?
+    assert_empty t.errors[:title]
+  end
+
   def test_if_validation_using_method_false
     # When the method returns false
-    Topic.validates_length_of(:title, maximum: 5, too_long: "hoo %{count}", if: :condition_is_true_but_its_not)
+    Topic.validates_length_of(:title, maximum: 5, too_long: "hoo %{count}", if: :condition_is_false)
     t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
     assert t.valid?
     assert_empty t.errors[:title]
@@ -36,7 +66,7 @@ class ConditionalValidationTest < ActiveModel::TestCase
 
   def test_unless_validation_using_method_false
     # When the method returns false
-    Topic.validates_length_of(:title, maximum: 5, too_long: "hoo %{count}", unless: :condition_is_true_but_its_not)
+    Topic.validates_length_of(:title, maximum: 5, too_long: "hoo %{count}", unless: :condition_is_false)
     t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
     assert t.invalid?
     assert t.errors[:title].any?
@@ -80,4 +110,19 @@ class ConditionalValidationTest < ActiveModel::TestCase
     assert t.errors[:title].any?
     assert_equal ["hoo 5"], t.errors["title"]
   end
+
+  def test_validation_using_conbining_if_true_and_unless_true_conditions
+    Topic.validates_length_of(:title, maximum: 5, too_long: "hoo %{count}", if: :condition_is_true, unless: :condition_is_true)
+    t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
+    assert t.valid?
+    assert_empty t.errors[:title]
+  end
+
+  def test_validation_using_conbining_if_true_and_unless_false_conditions
+    Topic.validates_length_of(:title, maximum: 5, too_long: "hoo %{count}", if: :condition_is_true, unless: :condition_is_false)
+    t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
+    assert t.invalid?
+    assert t.errors[:title].any?
+    assert_equal ["hoo 5"], t.errors["title"]
+  end
 end
diff --git a/activemodel/test/cases/validations/numericality_validation_test.rb b/activemodel/test/cases/validations/numericality_validation_test.rb
index 001815e28f..fbbaf8a30c 100644
--- a/activemodel/test/cases/validations/numericality_validation_test.rb
+++ b/activemodel/test/cases/validations/numericality_validation_test.rb
@@ -59,7 +59,7 @@ class NumericalityValidationTest < ActiveModel::TestCase
   end
 
   def test_validates_numericality_of_with_integer_only_and_symbol_as_value
-    Topic.validates_numericality_of :approved, only_integer: :condition_is_true_but_its_not
+    Topic.validates_numericality_of :approved, only_integer: :condition_is_false
 
     invalid!(NIL + BLANK + JUNK)
     valid!(FLOATS + INTEGERS + BIGDECIMAL + INFINITY)
diff --git a/activemodel/test/cases/validations/validates_test.rb b/activemodel/test/cases/validations/validates_test.rb
index 77cb8ebdc1..7f32f5dc74 100644
--- a/activemodel/test/cases/validations/validates_test.rb
+++ b/activemodel/test/cases/validations/validates_test.rb
@@ -62,17 +62,23 @@ class ValidatesTest < ActiveModel::TestCase
   end
 
   def test_validates_with_if_as_local_conditions
-    Person.validates :karma, presence: true, email: { unless: :condition_is_true }
+    Person.validates :karma, presence: true, email: { if: :condition_is_false }
     person = Person.new
     person.valid?
     assert_equal ["can't be blank"], person.errors[:karma]
   end
 
   def test_validates_with_if_as_shared_conditions
-    Person.validates :karma, presence: true, email: true, if: :condition_is_true
+    Person.validates :karma, presence: true, email: true, if: :condition_is_false
+    person = Person.new
+    assert person.valid?
+  end
+
+  def test_validates_with_unless_as_local_conditions
+    Person.validates :karma, presence: true, email: { unless: :condition_is_true }
     person = Person.new
     person.valid?
-    assert_equal ["can't be blank", "is not an email"], person.errors[:karma].sort
+    assert_equal ["can't be blank"], person.errors[:karma]
   end
 
   def test_validates_with_unless_shared_conditions
diff --git a/activemodel/test/models/person.rb b/activemodel/test/models/person.rb
index b61fdf76b1..8dd8ceadad 100644
--- a/activemodel/test/models/person.rb
+++ b/activemodel/test/models/person.rb
@@ -9,6 +9,10 @@ class Person
   def condition_is_true
     true
   end
+
+  def condition_is_false
+    false
+  end
 end
 
 class Person::Gender
diff --git a/activemodel/test/models/topic.rb b/activemodel/test/models/topic.rb
index 2f4e92c3b2..b0af00ee45 100644
--- a/activemodel/test/models/topic.rb
+++ b/activemodel/test/models/topic.rb
@@ -23,7 +23,7 @@ class Topic
     true
   end
 
-  def condition_is_true_but_its_not
+  def condition_is_false
     false
   end
 
-- 
cgit v1.2.3