aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
authorMattias Pfeiffer <mattias@pfeiffer.dk>2012-03-07 12:51:43 +0100
committerMattias Pfeiffer <mattias@pfeiffer.dk>2012-03-07 13:49:45 +0100
commit6185c4947e88f1b6b7c2adaabf62081bac6df04a (patch)
tree60d4684c80aacfe53004a73168acdc9c3627b71b /activerecord
parentd87ec9d3108afda28a5744d0b7edd328c3c284d1 (diff)
downloadrails-6185c4947e88f1b6b7c2adaabf62081bac6df04a.tar.gz
rails-6185c4947e88f1b6b7c2adaabf62081bac6df04a.tar.bz2
rails-6185c4947e88f1b6b7c2adaabf62081bac6df04a.zip
Add :conditions option to uniqueness validator
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/lib/active_record/validations/uniqueness.rb14
-rw-r--r--activerecord/test/cases/validations/uniqueness_validation_test.rb12
2 files changed, 24 insertions, 2 deletions
diff --git a/activerecord/lib/active_record/validations/uniqueness.rb b/activerecord/lib/active_record/validations/uniqueness.rb
index 9556878f63..eb3a34c4cc 100644
--- a/activerecord/lib/active_record/validations/uniqueness.rb
+++ b/activerecord/lib/active_record/validations/uniqueness.rb
@@ -35,8 +35,8 @@ module ActiveRecord
relation = relation.and(table[scope_item].eq(scope_value))
end
- if finder_class.unscoped.where(relation).exists?
- record.errors.add(attribute, :taken, options.except(:case_sensitive, :scope).merge(:value => value))
+ if finder_class.unscoped.where(relation).where(options[:conditions]).exists?
+ record.errors.add(attribute, :taken, options.except(:case_sensitive, :scope, :conditions).merge(:value => value))
end
end
@@ -102,6 +102,14 @@ module ActiveRecord
# validates_uniqueness_of :teacher_id, :scope => [:semester_id, :class_id]
# end
#
+ # It is also possible to limit the uniqueness constraint to a set of records matching certain conditions.
+ # In this example archived articles with are not being taken into consideration when validating uniqueness
+ # of the title attribute:
+ #
+ # class Article < ActiveRecord::Base
+ # validates_uniqueness_of :title, :conditions => ['status != ?', 'archived']
+ # end
+ #
# When the record is created, a check is performed to make sure that no record exists in the database
# with the given value for the specified attribute (that maps to a column). When the record is updated,
# the same check is made but disregarding the record itself.
@@ -109,6 +117,8 @@ module ActiveRecord
# Configuration options:
# * <tt>:message</tt> - Specifies a custom error message (default is: "has already been taken").
# * <tt>:scope</tt> - One or more columns by which to limit the scope of the uniqueness constraint.
+ # * <tt>:conditions</tt> - Specify the conditions to be included as a <tt>WHERE</tt> SQL fragment to limit
+ # the uniqueness constraint lookup. (e.g. <tt>:conditions => {:status => 'active'}</tt>)
# * <tt>:case_sensitive</tt> - Looks for an exact match. Ignored by non-text columns (+true+ by default).
# * <tt>:allow_nil</tt> - If set to true, skips this validation if the attribute is +nil+ (default is +false+).
# * <tt>:allow_blank</tt> - If set to true, skips this validation if the attribute is blank (default is +false+).
diff --git a/activerecord/test/cases/validations/uniqueness_validation_test.rb b/activerecord/test/cases/validations/uniqueness_validation_test.rb
index 79442d68b0..59d24f75e6 100644
--- a/activerecord/test/cases/validations/uniqueness_validation_test.rb
+++ b/activerecord/test/cases/validations/uniqueness_validation_test.rb
@@ -325,4 +325,16 @@ class UniquenessValidationTest < ActiveRecord::TestCase
assert w6.errors[:city].any?, "Should have errors for city"
assert_equal ["has already been taken"], w6.errors[:city], "Should have uniqueness message for city"
end
+
+ def test_validate_uniqueness_with_conditions
+ Topic.validates_uniqueness_of(:title, :conditions => ["approved = ?", true])
+ t1 = Topic.create("title" => "I'm a topic", "approved" => true)
+ t2 = Topic.create("title" => "I'm an unapproved topic", "approved" => false)
+
+ t3 = Topic.new("title" => "I'm a topic", "approved" => true)
+ assert !t3.valid?, "t3 shouldn't be valid"
+
+ t4 = Topic.new("title" => "I'm an unapproved topic", "approved" => false)
+ assert t4.valid?, "t4 should be valid"
+ end
end