Hello,
I used MongoDB before PostreSQL with an ODM called MongoEngine, which has a method for retrieving single results from the DB. It is similar to ActiveRecord find_by! as it raises an exception if no matching records are found. The difference is, it also raises an exception if more than one record matched the query. I’ve been looking for a similar feature in ActiveRecord but haven’t found any so far.
I’m currently using the following workaround, which works with chained where methods,
def ensure_unique
Ensures an Active Record query returns a single record, or raise exception
Usage: MyModel.where(foo: ‘bar’).where(baz: 'qux).ensure_unique
if self.many?
raise ActiveRecord::RecordNotUnique, 'More than one record matched criteria. A single match was expected.'
elsif self.empty?
raise ActiveRecord::RecordNotFound, 'No matching records were found. A single match was expected.'
else
# The where method always returns a collection, even when only one record is found.
# We want to return a single item.
return self.first
end
end
It could also be implemented as a query method (such as find_by!). However, I’d have to look further into it and find a way to support queries involving “AND” logic, such as chaining multiple where methods.
def find_unique_by!(*args)
Ensures an Active Record query returns a single record, or raise exception
Usage: MyModel.find_unique_by(foo: ‘bar’)
result = where(*args)
if result.many?
raise ActiveRecord::RecordNotUnique, 'More than one record matched criteria. A single match was expected.'
elsif result.empty?
raise ActiveRecord::RecordNotFound, 'No matching records were found. A single match was expected.'
else
return result.first
end
end
I’m wondering if the core team would approve the implementation of such feature. If positive, I would gladly write and commit it.
Best Regards,
Bruno Facca