Skip to content

Conversation

pfeiffer
Copy link
Contributor

@pfeiffer pfeiffer commented Mar 7, 2012

This commit adds a :conditions option to the uniqueness validator. The :conditions is added to the lookup used for determining the uniqueness of the attribute.

Example use-case:
An article with a title and a status. Status can be either draft, published or archived. We want to have unique titles - but only for non-archived articles. This cannot be accomplished using :scope => :status, since a draft article and a published article with identical titles both would be valid. This can now be accomplished with:

class Article < AR::Base
  validates :title, :uniqueness => {:conditions => ['status != ?', 'archived']}
end

In this case a draft article can have the same title as an archived article, but not the same name as a published article.

What do you think? Let me know if anything is missing - this is my first pull request to Rails.

@@ -35,8 +35,8 @@ def validate_each(record, attribute, value)
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?
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would prefer only to call the .where(options[:conditions]) if conditions are present - but didn't want to move too much around in this first take. Suggestions?

@josevalim
Copy link
Contributor

Thanks @pfeiffer. I believe something along these lines is convenient but I would rather allow a scope like where("status != 'archived'") than the old conditions hash.

@pfeiffer
Copy link
Contributor Author

pfeiffer commented Mar 7, 2012

@josevalim Great - I've pushed an update supporting where("..") instead of conditions hash.

@@ -102,6 +108,14 @@ module ClassMethods
# 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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the unwanted "with" please.

@pfeiffer
Copy link
Contributor Author

pfeiffer commented Mar 8, 2012

@vijaydev Done!

@pfeiffer
Copy link
Contributor Author

@josevalim Have you had time to review the changes?

josevalim added a commit that referenced this pull request Mar 17, 2012
Add :conditions option to uniqueness validator
@josevalim josevalim merged commit 4711298 into rails:master Mar 17, 2012
@josevalim
Copy link
Contributor

Merged, sorry for the delay. It somehow escaped my inbox. :)

@carlosantoniodasilva
Copy link
Member

@jonleighton hey, given AR is moving to a lazy approach for everything - from scopes to associations - I guess this should be changed to follow the same approach, wdyt?

@jonleighton
Copy link
Member

@carlosantoniodasilva yeah I guess so.

@carlosantoniodasilva
Copy link
Member

@pfeiffer hey, perhaps you want to take a look on that? Otherwise let me know and I'll try to take care of it later this week. Thanks!

senny added a commit to senny/rails that referenced this pull request Mar 9, 2013
This is a follow up to rails#5321 and follows the general direction in
AR to make things lazy evaluated.
carlosantoniodasilva added a commit that referenced this pull request Mar 9, 2013
Uniqueness validation uses a proc to specify the `:conditions` option.

This is a follow up to #5321 and follows the general direction in
AR to make things lazy evaluated.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants