Skip to content

Commit

Permalink
Added I18n support for uniqueness validation.
Browse files Browse the repository at this point in the history
  • Loading branch information
jonmagic committed Feb 18, 2011
1 parent 777d905 commit 8a50bec
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 53 deletions.
3 changes: 1 addition & 2 deletions lib/mongo_mapper/plugins/validations.rb
Expand Up @@ -16,7 +16,6 @@ def validates_associated(*attr_names)
end
end

# TODO: Add I18n support
class UniquenessValidator < ::ActiveModel::EachValidator
def initialize(options)
super(options.reverse_merge(:case_sensitive => true))
Expand All @@ -39,7 +38,7 @@ def validate_each(record, attribute, value)
conditions[:_id.ne] = record._id if record._id

if @klass.exists?(conditions)
record.errors.add(attribute, :taken, :default => options[:message], :value => value)
record.errors.add(attribute, :taken, options.except(:case_sensitive, :scope).merge(:value => value))
end
end

Expand Down
5 changes: 5 additions & 0 deletions test/fixtures/en.yml
@@ -0,0 +1,5 @@
en:
activemodel:
errors:
messages:
taken: "has already been taken"
108 changes: 57 additions & 51 deletions test/functional/test_validations.rb
Expand Up @@ -7,45 +7,45 @@ class ValidationsTest < Test::Unit::TestCase
key :name, String, :required => true
end
end

should "not insert document" do
doc = @document.new
doc.save
@document.count.should == 0
end

should "populate document's errors" do
doc = @document.new
doc.errors.size.should == 0
doc.save
doc.errors.full_messages.should == ["Name can't be blank"]
end
end

context "Saving a document that is invalid (destructive)" do
setup do
@document = Doc do
key :name, String, :required => true
end
end

should "raise error" do
doc = @document.new
lambda { doc.save! }.should raise_error(MongoMapper::DocumentNotValid)
end
end

context "Creating a document that is invalid (destructive)" do
setup do
@document = Doc do
key :name, String, :required => true
end
end

should "raise error" do
lambda { @document.create! }.should raise_error(MongoMapper::DocumentNotValid)
end

should "create a new document" do
instance = @document.create!(:name => "James")
instance.new_record?.should be_false
Expand All @@ -57,16 +57,16 @@ class ValidationsTest < Test::Unit::TestCase
@document = Doc do
key :name, String, :required => true
end

@doc = @document.create(:name => 'John Nunemaker')
end

should "not update document" do
@doc.name = nil
@doc.save
@doc.reload.name.should == 'John Nunemaker'
end

should "populate document's errors" do
@doc.name = nil
@doc.save
Expand All @@ -83,18 +83,18 @@ def action_present
end
end
end

should "work with validate :on => :create callback" do
@document.validate :action_present, :on => :create

doc = @document.create(:action => nil)
doc.should have_error_on(:action)

doc.action = 'kick'
doc.save
doc.should_not have_error_on(:action)
end

should "work with validate :on => :update callback" do
@document.validate :action_present, :on => :update

Expand Down Expand Up @@ -132,78 +132,84 @@ def action_present
end
doc = document.new("name" => "joe", :adult => true)
doc.save.should be_true

doc2 = document.new("name" => "joe", :adult => false)
doc2.should be_valid
end

should "work with i18n taken message" do
@document.create(:name => 'joe')
doc = @document.create(:name => 'joe')
doc.should have_error_on(:name, 'has already been taken')
end

should "allow to update an object" do
doc = @document.new("name" => "joe")
doc.save.should be_true

@document \
.stubs(:first) \
.with(:name => 'joe') \
.returns(doc)

doc.name = "joe"
doc.valid?.should be_true
doc.should_not have_error_on(:name)
end

should "fail if object name is not unique" do
doc = @document.new("name" => "joe")
doc.save.should be_true

@document \
.stubs(:first) \
.with(:name => 'joe') \
.returns(doc)

doc2 = @document.new("name" => "joe")
doc2.should have_error_on(:name)
end

should "allow multiple blank entries if :allow_blank => true" do
document = Doc do
key :name
validates_uniqueness_of :name, :allow_blank => :true
end

doc = document.new("name" => "")
doc.save.should be_true

document \
.stubs(:first) \
.with(:name => '') \
.returns(doc)

doc2 = document.new("name" => "")
doc2.should_not have_error_on(:name)
end

should "allow multiple nil entries if :allow_nil => true" do
document = Doc do
key :name
validates_uniqueness_of :name, :allow_nil => :true
end

doc = document.new('name' => nil)
doc.save.should be_true

doc2 = document.new('name' => nil)
doc2.should_not have_error_on(:name)
end

should "allow entries that differ only in case by default" do
document = Doc do
key :name
validates_uniqueness_of :name
end

doc = document.new("name" => "BLAMMO")
doc.save.should be_true

doc2 = document.new("name" => "blammo")
doc2.should_not have_error_on(:name)
end
Expand All @@ -215,29 +221,29 @@ def action_present
validates_uniqueness_of :name, :case_sensitive => false
end
end

should "fail on entries that differ only in case" do
doc = @document.new("name" => "BLAMMO")
doc.save.should be_true

doc2 = @document.new("name" => "blammo")
doc2.should have_error_on(:name)
end

should "not raise an error if value is nil" do
doc = @document.new("name" => nil)
lambda { doc.valid? }.should_not raise_error
end

should "not raise an error if special Regexp characters used" do
doc = @document.new("name" => '?')
lambda { doc.valid? }.should_not raise_error
end

should "check for uniqueness using entire string" do
doc = @document.new("name" => "John Doe")
doc.save.should be_true

doc2 = @document.new("name" => "John")
doc2.valid?.should be_true
end
Expand All @@ -251,29 +257,29 @@ def action_present
validates_uniqueness_of :name, :scope => :scope
end
end

should "fail if the same name exists in the scope" do
doc = @document.new("name" => "joe", "scope" => "one")
doc.save.should be_true

@document \
.stubs(:first) \
.with(:name => 'joe', :scope => "one") \
.returns(doc)

doc2 = @document.new("name" => "joe", "scope" => "one")
doc2.should have_error_on(:name)
end

should "pass if the same name exists in a different scope" do
doc = @document.new("name" => "joe", "scope" => "one")
doc.save.should be_true

@document \
.stubs(:first) \
.with(:name => 'joe', :scope => 'two') \
.returns(nil)

doc2 = @document.new("name" => "joe", "scope" => "two")
doc2.should_not have_error_on(:name)
end
Expand All @@ -288,29 +294,29 @@ def action_present
validates_uniqueness_of :name, :scope => [:first_scope, :second_scope]
end
end

should "fail if the same name exists in the scope" do
doc = @document.new("name" => "joe", "first_scope" => "one", "second_scope" => "two")
doc.save.should be_true

@document \
.stubs(:first) \
.with(:name => 'joe', :first_scope => 'one', :second_scope => 'two') \
.returns(doc)

doc2 = @document.new("name" => "joe", "first_scope" => "one", "second_scope" => "two")
doc2.should have_error_on(:name)
end

should "pass if the same name exists in a different scope" do
doc = @document.new("name" => "joe", "first_scope" => "one", "second_scope" => "two")
doc.save.should be_true

@document \
.stubs(:first) \
.with(:name => 'joe', :first_scope => 'one', :second_scope => 'one') \
.returns(nil)

doc2 = @document.new("name" => "joe", "first_scope" => "one", "second_scope" => "one")
doc2.should_not have_error_on(:name)
end
Expand All @@ -322,15 +328,15 @@ def action_present
# @document = Doc do
# key :name, String, :unique => true
# end
#
#
# doc = @document.create(:name => 'John')
# doc.should_not have_error_on(:name)
#
#
# @document \
# .stubs(:first) \
# .with(:name => 'John') \
# .returns(doc)
#
#
# second_john = @document.create(:name => 'John')
# second_john.should have_error_on(:name, 'has already been taken')
# end
Expand Down
2 changes: 2 additions & 0 deletions test/test_helper.rb
Expand Up @@ -102,3 +102,5 @@ def drop_indexes(klass)
MongoMapper.connection = Mongo::Connection.new('127.0.0.1', 27017, :logger => logger)
MongoMapper.database = "mm-test-#{RUBY_VERSION.gsub('.', '-')}"
MongoMapper.database.collections.each { |c| c.drop_indexes }

I18n.load_path << File.expand_path('../fixtures/en.yml', __FILE__)

0 comments on commit 8a50bec

Please sign in to comment.