[LRUG] Enforcing uniqueness

Roland Swingler roland.swingler at gmail.com
Fri Nov 11 06:37:26 PST 2011


Could you split Loans into current loans and past loans, and have a
table for each? Current Loans can then have a unique index on the
book_id column.

Roland

On Fri, Nov 11, 2011 at 2:22 PM, Andrew Stewart
<boss at airbladesoftware.com> wrote:
> Hola El Rug,
>
> Let's say I am modelling book libraries in ActiveRecord.  A library has many books and a book has many loans.  A loan is "current" while the book is out of the library; and, er, not current when the book is (back) in the library.
>
>    class Library < ActiveRecord::Base
>      has_many :books
>    end
>
>    class Book < ActiveRecord::Base
>      belongs_to :library
>      has_many :loans
>      has_one  :current_loan, :class_name => 'Loan', :conditions => 'loans.returned_at is null'
>    end
>
>    class Loan < ActiveRecord::Base
>      belongs_to :book
>    end
>
> I cannot figure out how to ensure a book can't end up with two current loans in the database.  I am seeing this at the moment due to, I believe, double-click form submissions in the GUI.
>
> Rails' uniqueness validator is vulnerable to race conditions, as my database attests.  The usual answer is to apply a unique index in the database.  But I want an index on the loans table like "unique(book_id) where returned_at is null" -- which isn't possible, as far as I know.
>
> I think there are four layers where this could be tackled:
>
> View: add client-side behaviour to prevent duplicate form submissions.
> => Mitigates the problem but doesn't really solve it.
>
> Controller: serialise access to the action where loans are created, perhaps per library (to reduce contention).
> => Mitigates the problem but doesn't really solve it.  Also I'm not sure how to implement.
>
> Model: use a validator
> => This is what I'm already doing.  It's not bullet proof.
>
> Database: use an index
> => I don't think it's possible given my data model.
>
> Given all of the above, I think the controller is my best bet.  But I'm not sure how to do it.
>
> Any ideas?
>
> Cheers,
> Andy Stewart
>
> -------
> http://airbladesoftware.com
> _______________________________________________
> Chat mailing list
> Chat at lists.lrug.org
> http://lists.lrug.org/listinfo.cgi/chat-lrug.org
>



More information about the Chat mailing list