Class-DBI

 view release on metacpan or  search on metacpan

README  view on Meta::CPAN

    Classname and an additional method, then that method will be called in
    turn on each of the objects being returned.

    The above is exactly equivalent to:

      Music::CD->has_many(_style_refs => 'Music::StyleRef');

      sub styles { 
        my $self = shift;
        return map $_->style, $self->_style_refs;
      }

    For an example of where this is useful see "MANY TO MANY RELATIONSHIPS"
    below.

   Cascading Delete
      Music::Artist->has_many(cds => 'Music::CD', { cascade => 'Fail' });

    It is also possible to control what happens to the 'child' objects when
    the 'parent' object is deleted. By default this is set to 'Delete' - so,
    for example, when you delete an artist, you also delete all their CDs,
    leaving no orphaned records. However you could also set this to 'None',
    which would leave all those orphaned records (although this generally
    isn't a good idea), or 'Fail', which will throw an exception when you
    try to delete an artist that still has any CDs.

    You can also write your own Cascade strategies by supplying a Class Name
    here.

    For example you could write a Class::DBI::Cascade::Plugin::Nullify which
    would set all related foreign keys to be NULL, and plug it into your
    relationship:

      Music::Artist->has_many(cds => 'Music::CD', { 
        cascade => 'Class::DBI::Cascade::Plugin::Nullify' 
      });

  might_have
      Music::CD->might_have(method_name => Class => (@fields_to_import));

      Music::CD->might_have(liner_notes => LinerNotes => qw/notes/);

      my $liner_notes_object = $cd->liner_notes;
      my $notes = $cd->notes; # equivalent to $cd->liner_notes->notes;

    might_have() is similar to has_many() for relationships that can have at
    most one associated objects. For example, if you have a CD database to
    which you want to add liner notes information, you might not want to add
    a 'liner_notes' column to your main CD table even though there is no
    multiplicity of relationship involved (each CD has at most one 'liner
    notes' field). So, you create another table with the same primary key as
    this one, with which you can cross-reference.

    But you don't want to have to keep writing methods to turn the the
    'list' of liner_notes objects you'd get back from has_many into the
    single object you'd need. So, might_have() does this work for you. It
    creates an accessor to fetch the single object back if it exists, and it
    also allows you import any of its methods into your namespace. So, in
    the example above, the LinerNotes class can be mostly invisible - you
    can just call $cd->notes and it will call the notes method on the
    correct LinerNotes object transparently for you.

    Making sure you don't have namespace clashes is up to you, as is
    correctly creating the objects, but this may be made simpler in later
    versions. (Particularly if someone asks for this!)

  Notes
    has_a(), might_have() and has_many() check that the relevant class has
    already been loaded. If it hasn't then they try to load the module of
    the same name using require. If the require fails because it can't find
    the module then it will assume it's not a simple require (i.e.,
    Foreign::Class isn't in Foreign/Class.pm) and that you will take care of
    it and ignore the warning. Any other error, such as a syntax error,
    triggers an exception.

    NOTE: The two classes in a relationship do not have to be in the same
    database, on the same machine, or even in the same type of database! It
    is quite acceptable for a table in a MySQL database to be connected to a
    different table in an Oracle database, and for cascading delete etc to
    work across these. This should assist greatly if you need to migrate a
    database gradually.

MANY TO MANY RELATIONSHIPS
    Class::DBI does not currently support Many to Many relationships, per
    se. However, by combining the relationships that already exist it is
    possible to set these up.

    Consider the case of Films and Actors, with a linking Role table with a
    multi-column Primary Key. First of all set up the Role class:

      Role->table('role');
      Role->columns(Primary => qw/film actor/);
      Role->has_a(film => 'Film');
      Role->has_a(actor => 'Actor');

    Then, set up the Film and Actor classes to use this linking table:

      Film->table('film');
      Film->columns(All => qw/id title rating/);
      Film->has_many(stars => [ Role => 'actor' ]);

      Actor->table('actor');
      Actor->columns(All => qw/id name/);
      Actor->has_many(films => [ Role => 'film' ]);

    In each case the 'mapping method' variation of has_many() is used to
    call the lookup method on the Role object returned. As these methods are
    the 'has_a' relationships on the Role, these will return the actual
    Actor and Film objects, providing a cheap many-to-many relationship.

    In the case of Film, this is equivalent to the more long-winded:

      Film->has_many(roles => "Role");

      sub actors { 
        my $self = shift;
        return map $_->actor, $self->roles 
      }

    As this is almost exactly what is created internally, add_to_stars and
    add_to_films will generally do the right thing as they are actually



( run in 2.042 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )