Validates_uniqueness_of across multiple rows?

Ok, that’s not the best subject line, but I couldn’t think of a
concise way to describe what I’m trying to do.

I’ve got two models. Grouping simply contains an id and a few other
attributes (e.g. rating). A grouping can contain many elements which
are stored the Element model.

A set of elements is tied together by a grouping_id. An element can
be one of several types of objects. I’m doing this with polymorphic
associations.

I need a way to ensure that a grouping is unique. That is, there
should not be two grouping_ids containing the exact same elements.

The closest analogy I can think of is a composite primary key.
Except, this is across multiple rows (instead of columns) and uses
polymorphic association types and ids.

Can this be easily done with Rails and ActiveRecord?

Thanks,
Raj

raji wrote:
[…]

I need a way to ensure that a grouping is unique. That is, there
should not be two grouping_ids containing the exact same elements.

The closest analogy I can think of is a composite primary key.
Except, this is across multiple rows (instead of columns) and uses
polymorphic association types and ids.

Can this be easily done with Rails and ActiveRecord?

Well, you could write a custom validator, something like (untested):
class Grouping < AR::B
validate :must_have_unique_elements

def must_have_unique_elements
taken = (elements.first.groupings.find :element_ids =>
element_ids).empty?
# There’s gotta be a more efficient way to write that query.

errors.add_to_base("That combination of elements already exists!") 

if taken
end
end

I don’t think there’s anything off the shelf to make this easier, but I
might be wrong…

Thanks,
Raj

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]

This isn’t something that’s going to be easy in any ORM, but here’s an
idea.

What about caching a list of the members of a Grouping in an
attribute? You’d need to include the type obviously, so it would look
something like this:

‘bar:1,bar:5,foo:2,frob:14’

You’d need to update this field when adding an element, and then
validates_uniqueness_of and/or unique key it in the DB.

Also note that you’ll want to sort it, otherwise you’ll run into
problems.

Dealing with users concurrently adding things to Groupings is a whole
'nother bucket of hurt, which will be trickier to deal with.

–Matt J.