create an entry for validates_uniquessness_of if one does not exist

This commit is contained in:
Jason Draper 2012-05-11 11:36:22 -04:00 committed by Gabe Berke-Williams
parent f5f64821a3
commit b618275a9d
4 changed files with 23 additions and 24 deletions

View File

@ -3,6 +3,10 @@
* Prefer Test::Unit to Minitest when loading integrations so that RubyMine is
happy (#88).
* `validates_uniqueness_of` will now create a record if one does not exist.
Previously, users were required to create a record in the database before
using this matcher.
# v1.2.0
* `ensure_inclusion_of` now has an `in_array` parameter:

View File

@ -30,12 +30,7 @@ Matchers to test validations and mass assignments:
it { should validate_presence_of(:body).with_message(/wtf/) }
it { should validate_presence_of(:title) }
it { should validate_numericality_of(:user_id) }
# validates_uniqueness_of requires an entry to be in the database already
it "validates uniqueness of title" do
Post.create!(title: "My Awesome Post", body: "whatever")
should validate_uniqueness_of(:title)
end
it { should validate_uniqueness_of(:title) }
end
describe User do

View File

@ -68,20 +68,25 @@ module Shoulda # :nodoc:
def matches?(subject)
@subject = subject.class.new
@expected_message ||= :taken
has_existing? &&
set_scoped_attributes &&
set_scoped_attributes &&
validate_attribute? &&
validate_after_scope_change?
end
private
def has_existing?
if @existing = @subject.class.find(:first)
true
else
@failure_message = "Can't find first #{class_name}"
false
def existing
@existing ||= first_instance
end
def first_instance
@subject.class.first || create_instance_in_database
end
def create_instance_in_database
@subject.class.new.tap do |instance|
instance.send("#{@attribute}=", "arbitrary_string")
instance.save(:validate => false)
end
end
@ -90,7 +95,7 @@ module Shoulda # :nodoc:
@options[:scopes].all? do |scope|
setter = :"#{scope}="
if @subject.respond_to?(setter)
@subject.send("#{scope}=", @existing.send(scope))
@subject.send("#{scope}=", existing.send(scope))
true
else
@failure_message = "#{class_name} doesn't seem to have a #{scope} attribute."
@ -114,7 +119,7 @@ module Shoulda # :nodoc:
true
else
@options[:scopes].all? do |scope|
previous_value = @existing.send(scope)
previous_value = existing.send(scope)
# Assume the scope is a foreign key if the field is nil
previous_value ||= 0
@ -144,7 +149,7 @@ module Shoulda # :nodoc:
end
def existing_value
value = @existing.send(@attribute)
value = existing.send(@attribute)
if @options[:case_insensitive] && value.respond_to?(:swapcase!)
value.swapcase!
end

View File

@ -34,13 +34,8 @@ describe Shoulda::Matchers::ActiveModel::ValidateUniquenessOfMatcher do
@matcher = validate_uniqueness_of(:attr)
end
it "should fail to require a unique value" do
@model.should_not @matcher
end
it "should alert the tester that an existing value is not present" do
@matcher.matches?(@model)
@matcher.negative_failure_message.should =~ /^Can't find first .*/
it "does not not require a created instance" do
@model.should @matcher
end
end
end