I had to do this exact thing a couple of years ago. <br><br>In postgres you can add a partial unique index <br><br>Something like "alter table loans add unique index (client_id) where status = "active"<br><br>
On Friday, 11 November 2011, Roland Swingler <<a href="mailto:roland.swingler@gmail.com">roland.swingler@gmail.com</a>> wrote:<br>> Could you split Loans into current loans and past loans, and have a<br>> table for each? Current Loans can then have a unique index on the<br>
> book_id column.<br>><br>> Roland<br>><br>> On Fri, Nov 11, 2011 at 2:22 PM, Andrew Stewart<br>> <<a href="mailto:boss@airbladesoftware.com">boss@airbladesoftware.com</a>> wrote:<br>>> Hola El Rug,<br>
>><br>>> 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.<br>
>><br>>> class Library < ActiveRecord::Base<br>>> has_many :books<br>>> end<br>>><br>>> class Book < ActiveRecord::Base<br>>> belongs_to :library<br>>> has_many :loans<br>
>> has_one :current_loan, :class_name => 'Loan', :conditions => 'loans.returned_at is null'<br>>> end<br>>><br>>> class Loan < ActiveRecord::Base<br>>> belongs_to :book<br>
>> end<br>>><br>>> 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.<br>
>><br>>> 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.<br>
>><br>>> I think there are four layers where this could be tackled:<br>>><br>>> View: add client-side behaviour to prevent duplicate form submissions.<br>>> => Mitigates the problem but doesn't really solve it.<br>
>><br>>> Controller: serialise access to the action where loans are created, perhaps per library (to reduce contention).<br>>> => Mitigates the problem but doesn't really solve it. Also I'm not sure how to implement.<br>
>><br>>> Model: use a validator<br>>> => This is what I'm already doing. It's not bullet proof.<br>>><br>>> Database: use an index<br>>> => I don't think it's possible given my data model.<br>
>><br>>> Given all of the above, I think the controller is my best bet. But I'm not sure how to do it.<br>>><br>>> Any ideas?<br>>><br>>> Cheers,<br>>> Andy Stewart<br>>><br>
>> -------<br>>> <a href="http://airbladesoftware.com">http://airbladesoftware.com</a><br>>> _______________________________________________<br>>> Chat mailing list<br>>> <a href="mailto:Chat@lists.lrug.org">Chat@lists.lrug.org</a><br>
>> <a href="http://lists.lrug.org/listinfo.cgi/chat-lrug.org">http://lists.lrug.org/listinfo.cgi/chat-lrug.org</a><br>>><br>> _______________________________________________<br>> Chat mailing list<br>> <a href="mailto:Chat@lists.lrug.org">Chat@lists.lrug.org</a><br>
> <a href="http://lists.lrug.org/listinfo.cgi/chat-lrug.org">http://lists.lrug.org/listinfo.cgi/chat-lrug.org</a><br>>