On Sunday, March 1, 2015 at 9:30:32 PM UTC-8, Tim Bates wrote:
>
> On Sunday, March 1, 2015 at 5:55:02 AM UTC+10:30, Jeremy Evans wrote:
>>
>> An alternative approach is just to add a method that checks that the
>> transaction is balanced:
>>
>
>> def DB.balanced_transaction(trans)
>> transaction do
>> yield
>> raise Sequel::ValidationFailed unless
>> trans.entries_dataset.sum(:amount) == 0
>> end
>> end
>>
>
> How might I ensure that all critical changes to a transaction or its
> entries (e.g. add, delete entry or change entry amount) go through this
> mechanism?
>
Modify all related code to call the method. In a well factored
application, there shouldn't be many points you have to modify.
If you want to be sure that that the constraint is enforced, it must be
enforced in the database. If you are doing anything serious with the data,
especially anything involving money, it would be a very bad idea to rely on
model validations to attempt to enforce consistency. As long as the
database is enforcing the constraint, the only time it would be important
to validate the data in the model is if you want to provide a nice error
message to the user and don't feel like trying to parse the constraint
violation exception (which is fairly easily to do reliably on PostgreSQL at
least).
> Another possible use case for a 'before_commit' hook might be to
>>> automatically save any unsaved objects when exiting a transaction block, to
>>> avoid the need to explicitly call 'save'. I'm not sure yet whether this is
>>> a good idea but having a 'before_commit' hook would make it easy to
>>> experiment with.
>>>
>>
>> I don't think you could do this without an identity map, that every new
>> model object registers with, which is not how Sequel::Model currently
>> works, or how I want it to work.
>>
>
> What I was thinking is that any change to a model object's attributes or
> associations would create a 'before_commit' hook that calls
> 'self.save_changes'. I'll try and see how easy this is to get working.
>
That sounds like a bad idea to me. I think persisting changes should be
explicit. There are good reasons why someone would update a model columns
value and later decide not to persist the changes.
DB.transaction do
model.set(:column=>value)
if model.some_method?
model.save
else
do_something_else
end
end
Additionally, if before_commit would operate like after_commit, then
calling it outside of a transaction would immediately invoke it. Since it
is common to set model column values outside a transaction and then persist
the changes inside a transaction (that's Sequel's default behavior,
actually), I'm not sure how that could work.
I apologize if I seem combative about this. It's just that I have an
accounting and auditing background and the specific example you gave threw
up red flags. :) It's possible that before_commit could have some useful
applications, though I can't think of a good example off the top of my head.
Thanks,
Jeremy
--
You received this message because you are subscribed to the Google Groups
"sequel-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sequel-talk.
For more options, visit https://groups.google.com/d/optout.