A number of discussions on this mailing list centre around how to manage
data integrity around multiple related objects. The classic example is a
transaction in a double-entry accounting system, where a transaction must
have at least two entries and all the entries of a transaction must sum to
zero:
class Transaction < Sequel::Model
one_to_many :entries
def validate
super
validates_min_length 2, :entries
errors.add(:entries, "must sum to zero") if
entries.inject(0){|s,e|s+e.amount} != 0
end
end
class Entry < Sequel::Model
many_to_one :transaction
end
This won't work because the entries can't be created until the transaction
is saved (we need a primary key for the transaction to associate the
entries). The usual recommendation is to use the 'nested_attributes' plugin
to create the transaction and the entries all together, but this is only
part of the story.
I would like to be able to do things like the following:
trans = Transaction.first(...)
DB.transaction do
trans.entries[0].amount += 10
trans.entries[0].save
trans.entries[1].amount -= 10
trans.entries[1].save
end
I would like the (database) transaction to be rolled back if and only if
the amounts don't balance, and the only time to check this is at the point
that the transaction is about to be committed, because until then Sequel
doesn't know if there are more changes to come.
Hence my suggestion / feature request is to have a 'before_commit' hook
that allows me to implement deferred validations, that are checked once all
changes have been made to a set of related objects and are about to be
committed. This then allows Sequel to mirror the behaviour of deferred
constraints, in databases that support them, or emulate them in databases
that don't.
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.
--
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.