validates_uniqueness_of and combo of three fields

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

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?

Max Williams 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

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