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.

Reply via email to