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