If you put the Rails model on the model, then you can control the flow without causing an exception.
class FolderItems belongs_to :item belongs_to :folder validates_uniqueness_of :item, scope: [:folder], on: :create end
Then you can use
FolderItem.create(folder: folder, item: item)
It will return true if the association was created, false if an error occurs. This exception will not be. Using FolderItem.create! will throw an exception if the association is not created.
The reason you see PG errors is because Rails itself believes that the model is valid when saved, because the model class does not have a uniqueness constraint in Rails. Of course, you have a unique database constraint that surprises Rails and makes it explode at the last minute.
If performance is critical, perhaps ignore this tip. Having a uniqueness constraint for the Rails model forces it to perform a SELECT before each INSERT so that it performs a uniqueness check at the Rails level, potentially doubling the number of queries your loop executes. Just catching bugs at the database level, as you do, can be a reasonable trade of elegance for performance.
(change) TL; DR: Always have a unique constraint in the database. Also, the presence of a model constraint will allow checking ActiveRecord / ActiveModel before the DB generates an error.
Chris aitchison
source share