Skip to content
Browse files

Ensure that validates_uniqueness_of works with with_scope. Closes #9235

…. [nik.wakelin, cavalle]

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@9168 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information...
1 parent cc2d6a0 commit 92cd8811aa3e113053a37bccb39cf5f09d9ef84d @lifo lifo committed Mar 31, 2008
View
2 activerecord/CHANGELOG
@@ -1,5 +1,7 @@
*SVN*
+* Ensure that validates_uniqueness_of works with with_scope. Closes #9235. [nik.wakelin, cavalle]
+
* Partial updates include only unsaved attributes. Off by default; set YourClass.partial_updates = true to enable. [Jeremy Kemper]
* Removing unnecessary uses_tzinfo helper from tests, given that TZInfo is now bundled [Geoff Buesing]
View
14 activerecord/lib/active_record/validations.rb
@@ -654,13 +654,15 @@ def validates_uniqueness_of(*attr_names)
condition_params << record.send(:id)
end
- results = connection.select_all(
- construct_finder_sql(
- :select => "#{attr_name}",
- :from => "#{finder_class.quoted_table_name}",
- :conditions => [condition_sql, *condition_params]
+ results = finder_class.with_exclusive_scope do
+ connection.select_all(
+ construct_finder_sql(
+ :select => "#{attr_name}",
+ :from => "#{finder_class.quoted_table_name}",
+ :conditions => [condition_sql, *condition_params]
+ )
)
- )
+ end
unless results.length.zero?
found = true
View
10 activerecord/test/cases/validations_test.rb
@@ -467,6 +467,16 @@ def test_validate_uniqueness_with_non_standard_table_names
assert i1.errors.on(:value), "Should not be empty"
end
+ def test_validates_uniqueness_inside_with_scope
+ Topic.validates_uniqueness_of(:title)
+
+ Topic.with_scope(:find => { :conditions => { :author_name => "David" } }) do
+ t1 = Topic.new("title" => "I'm unique!", "author_name" => "Mary")
+ assert t1.save
+ t2 = Topic.new("title" => "I'm unique!", "author_name" => "David")
+ assert !t2.valid?
+ end
+ end
def test_validate_straight_inheritance_uniqueness
w1 = IneptWizard.create(:name => "Rincewind", :city => "Ankh-Morpork")

2 comments on commit 92cd881

@mhorbul

The following code was working on rails 2.0 and doesn’t work on 2.1:

class Person < ActiveRecord::Base
validates_uniqueness_of :email

def self.find(*args) with_scope(:find => { :conditions => [“status = ?”, true]}) do super end end

end

>> p1 = Person.new(:email => “test@domain.com”, :status => true)
=> #<Person id: nil, email: “test@domain.com”, status: true>
>> p2 = Person.new(:email => “test@domain.com”, :status => true)
=> #<Person id: nil, email: “test@domain.com”, status: true>
>> p1.save!
=> true
>> p2.save!
ActiveRecord::RecordInvalid: Validation failed: Email has already been taken
>> p1 = Person.find(1)
=> #<Person id: 1, email: “test@domain.com”, status: true>
>> p1.status = false
=> false
>> p1.save!
=> true
>> p1 = Person.find(1)
ActiveRecord::RecordNotFound: Couldn’t find Person with ID=1
>> p2.save!
ActiveRecord::RecordInvalid: Validation failed: Email has already been taken
>> Person.find :all
=> []

@tarmo
tarmo commented on 92cd881 Jul 21, 2008

likonar, you are supposed to use validates_uniquenes_of :scope option, not with_scope to control the scope of this validation. If you really do want your validations to depend on the outside scope you really should make the intent explicit and implement a custom validation. Having validations depend on scope is too dangerous because most people probably wouldn’t expect it and the failure in this case would allow silent creation of invalid records (not really a mess one wants to be in).

Please sign in to comment.
Something went wrong with that request. Please try again.