On Tuesday, July 20, 2010 02:01:14 pm Jared Morgan wrote:
> I'm confused. I was under the impression that the only case in which
> save would not raise on error on failure is when validation fails
Digging around in the code a bit, this seems to be true.
> In this case, it's not the code that's
> the problem but rather user input. Right?
Not always.
For one, where is this assumption that every DM resource must be directly
related to user input? As an example, say I have a logging class of some sort
with a few required columns, and for whatever reason, I end up with a nil.
Which would you rather have happen in this situation:
- Exception is raised, the user gets a Fail Whale
- Exception is raised, the user gets a stack trace
- Exception is raised, caught, and logged without the user seeing a thing
- Invalid state is caught and logged without the user seeing a thing
- Invalid state is ignored, and this message SILENTLY SLIPS AWAY
Of these, I don't know about you, but the last is unacceptable to me. If I
fail to catch an exception, worst case, the user gets a stacktrace. If I fail
to make sure I saved, worst case, I LOSE DATA.
I apologize for the caps, but this is important, and I'm a bit surprised that
there's even an argument about it.
It's not just logging, it's _any_ ancilliary data I might generate with code,
rather than directly from HTTP. For example, I once had a User model and a
separate Email model, so users could have multiple email addresses (but only
one primary one). To keep things clean, I had an interface roughly like this:
class User
attr_accessor :email
belongs_to :primary_email, :model_name => 'Email'
before :save do
primary_email = Email.find_or_create_by_name email
...
end
end
...roughly. The idea was to expose only a single email address to the user,
but to delay verifying a new one until a confirmation email was sent.
Confirmation codes! That's a whole other model/table that no user should ever
have to touch directly.
> At
> least in the case of validations causing the failure, I'd much rather
> not have to handle an exception
I'd suggest something like 'try_save', rather than 'save', if we were able to
make breaking changes to the API at this point. (I don't know why I waited
till post-1.0 to bring this up again...)
> (and I don't consider an end-user
> mistyping something an exceptional situation). Am I missing something?
Even in this case, DataMapper is used outside of full-stack frameworks like
Rails. Say I've forgotten to add in any sort of validation. We're again stuck
with something like this (pseudocode):
put '/foos/:id' do |id|
obj = DataMapper.get id
obj.update params[:whatever]
redirect "/foos/#{id}", 303
end
Whoops. Yes, this was user input. No, it wasn't exceptional. But the user has
no clue what happened or why -- the best they can hope for is to look very
carefully at the resulting page to make sure it was updated correctly.
Now, I agree, it'd better if you can handle this sort of thing explicitly. But
if you've already got the code in place to do that, it should be a relatively
minor change to use a differently-named method, like 'try_save'. If you don't,
and you're counting on yourself to always do something like:
put '/foos/:id' do |id|
obj = DataMapper.get id
obj.update params[:whatever] || return 'Save failed!'
redirect "/foos/#{id}", 303
end
...you're just asking to lose data.
I think the place this annoys me the most is when I'm playing around in the
console, and I want to type something like some_list.each(&:save) -- whoops, I
have no idea if I did anything there.
--
You received this message because you are subscribed to the Google Groups
"DataMapper" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/datamapper?hl=en.