When using ActiveRecord finders that don't by throw a RecordNotFound exception I'm finding myself writing code like the following:
def show
@tag = Tag.find_by_name(params[:id]) or raise ActiveRecord::RecordNotFound
end
I don't really like the idea of raising a RecordNotFound myself, as, at the least, I don't get the exception message that ActiveRecord includes if it throws the exception internally ("Couldn't find Tag with ID=9999")... and it just feels... wrong.
Wouldn't it be better to have a finder option to specify you want an exception thrown if there's no record found?
def show
@tag = Tag.find_by_name(params[:id], :throw_not_found => true)
end
I’d prefer a bang! method. I think it’s a good indication that there should be separate ‘loading’ and ‘finding’ API – passing ever more options to find is getting weary.
Loading a unique record from the database is semantically different than finding a record that meets some criteria and it could be treated as such.
module ActiveRecord
class Base
def find!(*args)
records = find(args)
raise RecordNotFound, "Couldn't find #{name} without an ID" if records.blank?
records
end
end
end
works a treat. Adding ! to the method_missing finders might be a bit trickier.
So, if this `find!' bidness gets introduced it means an exception can get raised a) on record not found via find! / find_by_*! or b) on record not found via find(id). Raised on bangs or on non-bang.
I know the non-bang is a very specific circumstance, but does this bother anyone else? I suppose one way of looking at this is that the bang methods are just sugar for existing methods, none of which change. But it sure would be nice to just say "methods with a bang raise an exception on blank, methods without do not."
I can deal with it; I love that this change is being discussed. But won't someone think of the children?
I count on the fact that find(id) raises an exception. If I'm looking
up a model by id and it's not there, there's usually a problem. The
raises RecordNotFound exception is a convenient hook to render a 404
page.
If you really want it to return nil, why not use find_by_id ?