On Thu, Oct 07, 2004 at 08:14:53PM +0900, George  Moschovitis wrote:
> Comments from the Ruby
> community are critical in order to fix possible bugs and improve the
> API. Suggestions for missing features are also welcome. This version
> only supports the Postgres Database.

I'd like a database object mapping framework to remember the 'old' values of
properties at the time an object was read, and perform safe atomic updates.

e.g. sample
+---+-------+------+-------+
|id |  a    |  b   |  c    |
+---+-------+------+-------+
| 1 | hello | Ruby | world |
+---+-------+------+-------+

  obj = $db.get(1)       # a="hello", b="Ruby", c="world"
  ...
  obj.a = "goodbye"      # still remembers old_a = "hello"
  obj.b = "Perl"         # still remembers old_b = "Ruby"
  obj.save

generates:

(1) lax

  UPDATE sample SET a='goodbye',b='Perl' WHERE id=1 AND
    (a='hello' OR a='goodbye') AND (b='Ruby' OR b='Perl');
or
(2) strict

  UPDATE sample SET a='goodbye',b='Perl' WHERE id=1 AND
    a='hello' AND b='Ruby';

and raises an exception if the row processed count = 0. That stops
simultaneous updates stamping on each other. The 'strict' version is useful
for counters, sequences etc.

If this exception occurs, it's then easy enough to query the database to get
a set of (keys,values) where the value in the database is not consistent
with the value you're trying to save, to allow the user to resolve the
conflict:

  # this needs wrapping in a method, iterating across all properties
  obj2 = $db.get(1)
  diff = {}
  diff[:a] = [obj.a, obj2.a] if (obj2.a != obj.old_a AND obj2.a != obj.a)
  diff[:b] = [obj.b, obj2.b] if (obj2.b != obj.old_b AND obj2.b != obj.b)
  obj.old_a = obj2.a
  obj.old_b = obj2.b

These 'old' properties might also be useful for object-level transactions,
without serialisation as ActiveRecord/Transaction::Simple does.

Regards,

Brian.