I'd just like to know what other people think of my interpretation of
#save/#save!.
Currently (0.9.x) the behaviour is:
#save: save, return true/false depending on success
#save!: save unvalidated; raise exception on persistence error
My reaction to this is that - ahem - banging the operation changes
*two* things about #save: it disables validations and it enables
propagation of persistence errors. To me, this makes the behaviour
surprising.
I think that having a #save method that catches all errors is
important - it means you can guarantee your app will not generated an
unexpected 500 error. In other words, I'm happy with the current #save.
In specs, having the examples fail fast is important. One of the two
main conventions of #<method>! is to raise errors (the other being to
modify the receiver). So I'm happy that #save! reraises persistence
errors.
BUT, #save! also disables validations. This means that in a spec, you
might create an invalid object that saves with #save!, but save
silently fails.
To me, these are two dimensions of one problem and need separating,
possibly with methods like this:
#save
#save!
#save_without_validations
#save_without_validations!
WDYAT?
Cheers
Ashley
--
http://www.patchspace.co.uk/
http://www.linkedin.com/in/ashleymoran
http://aviewfromafar.net/
http://twitter.com/ashleymoran
> The intention with the 0.10 behavior is:
>
> #save - save the resource with hooks applied
> #save! - save the resource without any hooks applied
>
> Also #create, #destroy, #update all should conform to this behavior
> across Resource, Collection and Model.
I did not know about the convention beforehand. Can you explain what
the thinking behind the saving without hooks is? (Sorry for the dumb
question - it may be an application of the convention you explain
below.)
>> One of the two
>> main conventions of #<method>! is to raise errors (the other being to
>> modify the receiver). So I'm happy that #save! reraises persistence
>> errors.
>
> I think the bang/non-bang convention you mention is actually Rails
> specific. With DM we're trying to design according to the following
> interpretation of their usage:
>
> http://dablog.rubypal.com/2007/8/15/bang-methods-or-danger-will-rubyist
>
> So the non-bang version is considered safe, and the bang is unsafe.
> The bang method bypasses checks, and any tests that may have been
> installed by plugins (like dm-constraints and dm-validations) and just
> goes straight to the datastore and modifies the data directly.
Yes, that's a better convention than the one I understood.
>> I think that having a #save method that catches all errors is
>> important - it means you can guarantee your app will not generated an
>> unexpected 500 error. In other words, I'm happy with the current
>> #save.
>
> Actually in most cases we don't attempt to catch datastore
> exceptions. We just let them bubble them up. It might look like we
> catch all errors, but that's not us, that's you using dm-validations
> and dm-constraints. Those libs act as a gate keeper in front of the
> datastore, short circuiting alot of things that wouldn't work before
> the datastore even sees them. By the time a datastore exception
> happens it's usually too late for DM to recover in a sane consistent
> manner anyway, so I would only consider catching those exceptions if I
> was to add more debug info, and then rethrow the exception up the
> stack.
Thanks for the explanation. The only problem I can see, is that
datastore exceptions are datastore-specific, and therefore break the
abstraction that DataMapper makes over persistence mechanisms? Is
this correct thinking, or is there another perspective?
Thanks