Multiple scopes with validates_uniqueness_of in Rails

Posted in Programming at 3:24 pm by matt

Previously, I talked about Validates_uniqueness_of and scope in rails

Well, what happens if you’ve got a case where, say you’re selling widgets, and you’ve got a join model set up with has_many :through relations, and you’re working with the following table:

(we’re listing stores that sell our widgets, and what size and price they sell them for)

Table: saleitems

Columns: widget_id, store_id, size, price

So, now, we want to validate that a widget can be sold at any store, and a widget can be sold many times at one store, but we can only sell a widget-store-size combo once. (You can’t sell a LARGE widget twice at the same store)

I think I was wrong, previously in my understanding. Now, I’ve written some code and see that you do the following:

You add a “validate_on_create” function to your saleitems model, and it looks like this:

def validate_on_create
   if Store.find_by_widget_id_and_size_and_store_id(widget_id, size, store_id)
   errors.add(‘you can’t do that’)


Thanks to: Rails Weenie for the answer

technorati tags:, , ,

1 Comment »

  1. Emergent Properties » Rails and the MySQL Unique Index with validates_uniqueness_of said,

    June 22, 2006 at 3:26 pm

    […] Update: I’ve corrected some of my misconceptions about using multiple scopes with one validates uniqueness of.  Read the article. […]

  2. Andrew Grimm said,

    October 13, 2007 at 10:04 pm

    I’m new to RoR, but why are you using validate_on_create rather than validate?

  3. Andrew Grimm said,

    October 13, 2007 at 11:07 pm

    After spending an hour or so googling for an answer, I decided to just try the equivalent of

    validates_uniqueness_of :widget_id, :scope => [:store_id, :size]
    validates_uniqueness_of :store_id, :scope => [:widget_id, :size]
    validates_uniqueness_of :size, :scope => [:store_id, :widget_id]

    and see if it worked. And for me, using a recent version of everything, it did.


  4. Cameron said,

    December 27, 2007 at 11:52 pm

    I think that using validates_uniqueness_of :widget_id, :scope => [ :size, :store_id ] works just fine — but it seems to fail silently. Creating the validate_on_create function as you are showing would at least raise an error message.

Leave a Comment