# Validates\_uniqueness\_of and combo of three fields

**URL:** <https://www.ruby-forum.com/t/validates-uniqueness-of-and-combo-of-three-fields/130597>\
**Category:** Rails\
**Created:** [February 29, 2008, 6:29pm UTC](https://www.ruby-forum.com/t/validates-uniqueness-of-and-combo-of-three-fields/130597 "2008-02-29T18:29:41Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![cmaxvv](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/85f322/32.png) [@cmaxvv](https://www.ruby-forum.com/u/cmaxvv)\
**Post date:** [February 29, 2008, 6:29pm UTC](https://www.ruby-forum.com/t/validates-uniqueness-of-and-combo-of-three-fields/130597/1 "2008-02-29T18:29:41Z")

</div>

I have a model, Property, that has\_many\_polymorphs. The associated join  
table (labellings) has fields:  
id (simple record id),  
property\_id,  
labellable\_id  
labellable\_type.

It’s basically the same system used with acts\_as\_taggable, except that  
Property objects are a tree instead of a simple list (which doesn’t have  
any bearing on this problem, i think).

If i add a property to an object then a join table entry is created. If  
i add it again, i now have the object labelled twice with the same  
property, which i don’t want. I could say

object.properties \<\< prop unless object.properties.include? prop

But that’s a bit cumbersome.

Ideally i’d use validates\_uniqueness\_of - i know that i can do this for  
a combo of two values, with, eg

validates\_uniqueness\_of :property\_id, :scope =\> :labellable\_id

But i don’t know how to do it for three fields. I tried this:

validates\_uniqueness\_of :property\_id, :scope =\> [:labellable\_id,  
:labellable\_type]

but got this exception when i tested it:  
ActiveRecord::RecordInvalid: Validation failed: Property has already  
been taken

Anyone know how to do this?

thanks  
max

---

<div class="post-metadata">

**Author:** ![cmaxvv](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/85f322/32.png) [@cmaxvv](https://www.ruby-forum.com/u/cmaxvv)\
**Post date:** [February 29, 2008, 6:35pm UTC](https://www.ruby-forum.com/t/validates-uniqueness-of-and-combo-of-three-fields/130597/2 "2008-02-29T18:35:03Z")

</div>

Actually my syntax (validates\_uniqueness\_of :property\_id, :scope =\>  
[:labellable\_id, :labellable\_type]) is correct, but i want it to simply  
fail to save, rather than raise an exception. Does anyone know how to  
do this?

---

<div class="post-metadata">

**Author:** ![cmaxvv](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/85f322/32.png) [@cmaxvv](https://www.ruby-forum.com/u/cmaxvv)\
**Post date:** [February 29, 2008, 11:43pm UTC](https://www.ruby-forum.com/t/validates-uniqueness-of-and-combo-of-three-fields/130597/3 "2008-02-29T23:43:17Z")

</div>

Max W. wrote:

> Actually my syntax (validates\_uniqueness\_of :property\_id, :scope =\>  
> [:labellable\_id, :labellable\_type]) is correct, but i want it to simply  
> fail to save, rather than raise an exception. Does anyone know how to  
> do this?

instead of model.save! or model.update!, use the form

if model.save

# my model was saved successfully

else

# my model didn’t save

end

also note

model.valid?

model.errors

hth

ilan

---

<div class="post-metadata">

**Author:** ![cmaxvv](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/85f322/32.png) [@cmaxvv](https://www.ruby-forum.com/u/cmaxvv)\
**Post date:** [March 1, 2008, 12:30pm UTC](https://www.ruby-forum.com/t/validates-uniqueness-of-and-combo-of-three-fields/130597/4 "2008-03-01T12:30:11Z")

</div>

> instead of model.save! or model.update!, use the form
> 
> if model.save
> 
> # my model was saved successfully
> 
> else
> 
> # my model didn’t save
> 
> end

Thanks Ilan - i played around with this a bit more and narrowed my  
problem down a bit. It’s actually only the \<\< (push) operator that  
breaks horribly - save just quietly fails, which is what i want. So, as  
a way of adding a label (join table entry) to an object (eg of class  
Lesson) this works fine (ie fails without raising):

Label.create(:property\_id =\> @prop.id, :labellable\_id =\> @object.id,  
:labellable\_type =\> @object.class.to\_s)

However, it’s a bit clunky. I’d rather just write

@prop.lessons \<\< @object

But this _does_ raise when it fails, ie if the join table entry exists  
already.

I can sort of get around it by doing

@prop.lessons \<\< @object rescue false

but it would be nice to not have to do that. I guess my problem is just  
with the \<\< method. Any ideas?

thanks  
max
