[jifty-devel] Serious thought on relationships

Andrew Sterling Hanenkamp sterling at hanenkamp.com
Wed Aug 15 18:10:20 EDT 2007


I spent much of today consider what can be done for relationships
particularly after the discussion last month ("Regarding refers_to and by on
JDBI columns"). I think I've got a plan for a number of handy updates
relating to relationships.

I'm already working on a patch to implement Idea 1. I think (at least the
indirect record part) keeps things more consistent. The rest are sugar and
I'll work to implement them too if everyone (particularly Jesse :) like B
and III.

Idea 1: Handling indirect relationships completely

Currently, Jifty handles two types of relationships that I call "direct
record" and "indirect collection".

Direct Record: You can uses the C<references> keyword to create a column in
one model referring to a record in another model.

Indirect Collection: You can use the C<references> keyword with the C<by>
keyword to create a virtual column that returns a collection of records such
that the by column in the foreign records match the ID column of the current
record.

However, I think some effort will allow this to be expanded to handle two
additional situations:

Indirect Record: This would allow the C<references> keyword with the C<by>
keyword to create a virtual column that returns a single record such that by
column in the foreign record matches the ID column of the current record.
This would allow you to traverse a one-to-one relationship in both
directions. For example,

  package App::Model::Employee;
  use Jifty::DBI::Schema;
  use App::Record schema {
      column name => type is 'text';
      column bio  => references App::Model::Bio, is distinct;
  };

  package App::Model::Bio;
  use Jifty::DBI::Schema;
  use App::Record schema {
      column employee => references App::Model::Employee by 'bio';
      column biography => type is 'text';
  };


Indirect Collection with Dereferencing: This adds a new keyword that would
be used with C<reference> and C<by> called C<dereference>. Basically, the
C<dereference> keyword would look up the the given column in the foreign
model, which must be a reference to a record, and change the generated
collection reference to return a collection for that record instead. This
would allow you to have a many-to-many relationship with an invisible link
table. For example,

  package App::Model::Employee;
  use Jifty::DBI::Schema;
  use App:Record schema {
      column name => type is 'text';
      column supervisors => references App::Model::ManagerCollection
                                    by 'supervisee',
                           dereference 'supervisor';
      column supervisees => references App::Model::ManagerCollection
                                    by 'supervisor',
                           dereference 'supervisee';
  };

  package App::Model::Manager;
  use Jifty::DBI::Schema;
  use App::Record schema {
      column supervisor => references App::Model::Employee;
      column supervisee => references App::Model::Employee;
  };

Idea B: Adding reverse mutators to indirect relationships

The second step would be to add mutators to the indirect relationships
allowing one to call backwards across a reverse relationship.

For collections, this would include an add_to_* and a delete_from_* methods
for creating and deleting records related to a collection.

For records, this would include a set_* which would perform the set
operation on the passed record object (or load the record from the passed ID
and then set).

Idea III: Adding the ability to create back-references in the originating
file.

Sometimes, it would be nice to be able to create the method calls to go from
one direction to the other, but you don't have control over the foreign
model. The specific possibility that could come up is in plugins, now that
they can have their own models (blame me). It would be nice if the
application could use tell Jifty to insert the back-reference methods in the
other model.

For example, here's a typical one-to-many relationship using the
C<backreference> keyword as I imagine it:

  package App::Model::Employee;
  use Jifty::DBI::Schema;
  use App::Record schema {
      column name => type is 'text';
  };

  package App::Model::Address;
  use Jifty::DBI::Schema;
  use App::Record schema {
      column employee => references App::Model::Employee,
                      backreference 'addresses';
      column name => type is 'text';
      column address => type is 'text';
  };

With some help, similar logic could be applied to the indirect record and
indirect collection with dereferencing examples above too.

Cheers,
Andrew
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.bestpractical.com/pipermail/jifty-devel/attachments/20070815/064e6d16/attachment.htm


More information about the jifty-devel mailing list