On Mon, Feb 22, 2010 at 4:54 PM, Grary <grary.sti...@gmail.com> wrote:
> Thanks Fred.
>
> What do you mean by 'use a unique index'?
>
> What I am concerned about is logical uniqueness, i.e., persist only
> data objects with a unique combination of attributes.
>

So if I understand correctly, lets say there are two attributes a, and b

You want to make sure that no two models have the same COMBINATION of
values for a and b,

so having two models with:

a = 1, b = 2
a = 1, b = 3

would not be a conflict

If that's the case then the standard validation

class Widget < ActiveRecord::Base
  validates_uniqueness_of :a, :b
end

wouldn't work since it tries to prevent saving two models with the
same value of a, OR with the same value of b

And even if that's not what you're trying to do, and you're ok with
the example being a conflict, Fred's point is that
validates_uniqueness_of doesn't guarantee uniqueness if two users try
to save conflicting records simultaneously.  The validation works by
first trying to find a record with the value, and if it doesn't find
it inserting the 'new' record, and this can fail due to a concurrency
hole.

To fill this hole requires leaning on the database server, and the way
to do that in SQL is by having a unique index on the table which
covers the column or columns you want to be unique. This assume you
are using a database which supports it, e.g. MySql.

To create an index you can create a migration which includes a statement like

   add_index  :widgets, [:a, :b], :unique => true)

Assuming that the table name for the model is 'widgets'

Now if you do this, you also need to be aware that if you try to save
a record with a uniqueness conflict the save will raise an
ActiveRecord::StatementInvalid exception, which you'll need to rescue
and do something like telling the user of the conflict so that he can
resolve it.
-- 
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

-- 
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Talk" group.
To post to this group, send email to rubyonrails-t...@googlegroups.com.
To unsubscribe from this group, send email to 
rubyonrails-talk+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/rubyonrails-talk?hl=en.

Reply via email to