提交 93898b38 编写于 作者: J José Valim

Ensure new validates works with uniqueness validator.

上级 d4589e96
......@@ -40,8 +40,7 @@ module ClassMethods
# not occur (e.g. <tt>:unless => :skip_validation</tt>, or <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>). The
# method, proc or string should return or evaluate to a true or false value.
def validates_associated(*attr_names)
options = attr_names.extract_options!
validates_with AssociatedValidator, options.merge(:attributes => attr_names)
validates_with AssociatedValidator, _merge_attributes(attr_names)
end
end
end
......
......@@ -2,10 +2,14 @@ module ActiveRecord
module Validations
class UniquenessValidator < ActiveModel::EachValidator
def initialize(options)
@klass = options.delete(:klass)
super(options.reverse_merge(:case_sensitive => true))
end
# Unfortunately, we have to tie Uniqueness validators to a class.
def setup(klass)
@klass = klass
end
def validate_each(record, attribute, value)
finder_class = find_finder_class_for(record)
table = finder_class.active_relation
......@@ -170,8 +174,7 @@ module ClassMethods
# such a case.
#
def validates_uniqueness_of(*attr_names)
options = attr_names.extract_options!
validates_with UniquenessValidator, options.merge(:attributes => attr_names, :klass => self)
validates_with UniquenessValidator, _merge_attributes(attr_names)
end
end
end
......
......@@ -10,33 +10,29 @@
class AssociationValidationTest < ActiveRecord::TestCase
fixtures :topics, :owners
repair_validations(Topic, Reply)
repair_validations(Topic, Reply, Owner)
def test_validates_size_of_association
repair_validations(Owner) do
assert_nothing_raised { Owner.validates_size_of :pets, :minimum => 1 }
o = Owner.new('name' => 'nopets')
assert !o.save
assert o.errors[:pets].any?
pet = o.pets.build('name' => 'apet')
assert o.valid?
end
assert_nothing_raised { Owner.validates_size_of :pets, :minimum => 1 }
o = Owner.new('name' => 'nopets')
assert !o.save
assert o.errors[:pets].any?
pet = o.pets.build('name' => 'apet')
assert o.valid?
end
def test_validates_size_of_association_using_within
repair_validations(Owner) do
assert_nothing_raised { Owner.validates_size_of :pets, :within => 1..2 }
o = Owner.new('name' => 'nopets')
assert !o.save
assert o.errors[:pets].any?
assert_nothing_raised { Owner.validates_size_of :pets, :within => 1..2 }
o = Owner.new('name' => 'nopets')
assert !o.save
assert o.errors[:pets].any?
pet = o.pets.build('name' => 'apet')
assert o.valid?
pet = o.pets.build('name' => 'apet')
assert o.valid?
2.times { o.pets.build('name' => 'apet') }
assert !o.save
assert o.errors[:pets].any?
end
2.times { o.pets.build('name' => 'apet') }
assert !o.save
assert o.errors[:pets].any?
end
def test_validates_associated_many
......@@ -55,51 +51,43 @@ def test_validates_associated_many
end
def test_validates_associated_one
repair_validations(Reply) do
Reply.validates_associated( :topic )
Topic.validates_presence_of( :content )
r = Reply.new("title" => "A reply", "content" => "with content!")
r.topic = Topic.create("title" => "uhohuhoh")
assert !r.valid?
assert r.errors[:topic].any?
r.topic.content = "non-empty"
assert r.valid?
end
Reply.validates :topic, :associated => true
Topic.validates_presence_of( :content )
r = Reply.new("title" => "A reply", "content" => "with content!")
r.topic = Topic.create("title" => "uhohuhoh")
assert !r.valid?
assert r.errors[:topic].any?
r.topic.content = "non-empty"
assert r.valid?
end
def test_validates_associated_with_custom_message_using_quotes
repair_validations(Reply) do
Reply.validates_associated :topic, :message=> "This string contains 'single' and \"double\" quotes"
Topic.validates_presence_of :content
r = Reply.create("title" => "A reply", "content" => "with content!")
r.topic = Topic.create("title" => "uhohuhoh")
assert !r.valid?
assert_equal ["This string contains 'single' and \"double\" quotes"], r.errors[:topic]
end
Reply.validates_associated :topic, :message=> "This string contains 'single' and \"double\" quotes"
Topic.validates_presence_of :content
r = Reply.create("title" => "A reply", "content" => "with content!")
r.topic = Topic.create("title" => "uhohuhoh")
assert !r.valid?
assert_equal ["This string contains 'single' and \"double\" quotes"], r.errors[:topic]
end
def test_validates_associated_missing
repair_validations(Reply) do
Reply.validates_presence_of(:topic)
r = Reply.create("title" => "A reply", "content" => "with content!")
assert !r.valid?
assert r.errors[:topic].any?
Reply.validates_presence_of(:topic)
r = Reply.create("title" => "A reply", "content" => "with content!")
assert !r.valid?
assert r.errors[:topic].any?
r.topic = Topic.find :first
assert r.valid?
end
r.topic = Topic.find :first
assert r.valid?
end
def test_validates_size_of_association_utf8
repair_validations(Owner) do
with_kcode('UTF8') do
assert_nothing_raised { Owner.validates_size_of :pets, :minimum => 1 }
o = Owner.new('name' => 'あいうえおかきくけこ')
assert !o.save
assert o.errors[:pets].any?
o.pets.build('name' => 'あいうえおかきくけこ')
assert o.valid?
end
with_kcode('UTF8') do
assert_nothing_raised { Owner.validates_size_of :pets, :minimum => 1 }
o = Owner.new('name' => 'あいうえおかきくけこ')
assert !o.save
assert o.errors[:pets].any?
o.pets.build('name' => 'あいうえおかきくけこ')
assert o.valid?
end
end
......
......@@ -38,7 +38,7 @@ class Thaumaturgist < IneptWizard
class UniquenessValidationTest < ActiveRecord::TestCase
fixtures :topics, 'warehouse-things', :developers
repair_validations(Topic)
repair_validations(Topic, Reply)
def test_validate_uniqueness
Topic.validates_uniqueness_of(:title)
......@@ -58,6 +58,15 @@ def test_validate_uniqueness
assert t2.save, "Should now save t2 as unique"
end
def test_validates_uniqueness_with_validates
Topic.validates :title, :uniqueness => true
t = Topic.create!('title' => 'abc')
t2 = Topic.new('title' => 'abc')
assert !t2.valid?
assert t2.errors[:title]
end
def test_validates_uniqueness_with_newline_chars
Topic.validates_uniqueness_of(:title, :case_sensitive => false)
......@@ -66,24 +75,22 @@ def test_validates_uniqueness_with_newline_chars
end
def test_validate_uniqueness_with_scope
repair_validations(Reply) do
Reply.validates_uniqueness_of(:content, :scope => "parent_id")
Reply.validates_uniqueness_of(:content, :scope => "parent_id")
t = Topic.create("title" => "I'm unique!")
t = Topic.create("title" => "I'm unique!")
r1 = t.replies.create "title" => "r1", "content" => "hello world"
assert r1.valid?, "Saving r1"
r1 = t.replies.create "title" => "r1", "content" => "hello world"
assert r1.valid?, "Saving r1"
r2 = t.replies.create "title" => "r2", "content" => "hello world"
assert !r2.valid?, "Saving r2 first time"
r2 = t.replies.create "title" => "r2", "content" => "hello world"
assert !r2.valid?, "Saving r2 first time"
r2.content = "something else"
assert r2.save, "Saving r2 second time"
r2.content = "something else"
assert r2.save, "Saving r2 second time"
t2 = Topic.create("title" => "I'm unique too!")
r3 = t2.replies.create "title" => "r3", "content" => "hello world"
assert r3.valid?, "Saving r3"
end
t2 = Topic.create("title" => "I'm unique too!")
r3 = t2.replies.create "title" => "r3", "content" => "hello world"
assert r3.valid?, "Saving r3"
end
def test_validate_uniqueness_scoped_to_defining_class
......@@ -102,29 +109,27 @@ def test_validate_uniqueness_scoped_to_defining_class
end
def test_validate_uniqueness_with_scope_array
repair_validations(Reply) do
Reply.validates_uniqueness_of(:author_name, :scope => [:author_email_address, :parent_id])
Reply.validates_uniqueness_of(:author_name, :scope => [:author_email_address, :parent_id])
t = Topic.create("title" => "The earth is actually flat!")
t = Topic.create("title" => "The earth is actually flat!")
r1 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're crazy!", "content" => "Crazy reply"
assert r1.valid?, "Saving r1"
r1 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're crazy!", "content" => "Crazy reply"
assert r1.valid?, "Saving r1"
r2 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're crazy!", "content" => "Crazy reply again..."
assert !r2.valid?, "Saving r2. Double reply by same author."
r2 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're crazy!", "content" => "Crazy reply again..."
assert !r2.valid?, "Saving r2. Double reply by same author."
r2.author_email_address = "jeremy_alt_email@rubyonrails.com"
assert r2.save, "Saving r2 the second time."
r2.author_email_address = "jeremy_alt_email@rubyonrails.com"
assert r2.save, "Saving r2 the second time."
r3 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy_alt_email@rubyonrails.com", "title" => "You're wrong", "content" => "It's cubic"
assert !r3.valid?, "Saving r3"
r3 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy_alt_email@rubyonrails.com", "title" => "You're wrong", "content" => "It's cubic"
assert !r3.valid?, "Saving r3"
r3.author_name = "jj"
assert r3.save, "Saving r3 the second time."
r3.author_name = "jj"
assert r3.save, "Saving r3 the second time."
r3.author_name = "jeremy"
assert !r3.save, "Saving r3 the third time."
end
r3.author_name = "jeremy"
assert !r3.save, "Saving r3 the third time."
end
def test_validate_case_insensitive_uniqueness
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册