Working on a many-to-many CDBI::Relationship

[prev] [thread] [next] [Date index for 2005/05/14]

From: Stepan Riha
Subject: Working on a many-to-many CDBI::Relationship
Date: 00:25 on 14 May 2005
I'm working on a CDBI::Relationship plugin wich adds an "associated_with" CDBI
class method for specifying many-to-many relationships. I've got a question on
the proper way to plug the "many_to_many" method into the CDBI class that uses
it.  Do I simply do it in the BEGIN block of my plugin class?  This works,
however my code adds it to the CDBI class but one would probably prefer it be
added to the class that "uses" it (University::DBI, in my example).

Right now, this is how I do it:

---------------------------------------------------------------------
package Class::DBI::Relationship::AssociatedWith;
use base 'Class::DBI::Relationship';
BEGIN {
	Class::DBI->add_relationship_type(
		associated_with => "Class::DBI::Relationship::AssociatedWith"
	);
}
---------------------------------------------------------------------

In a class that inherits from CDBI and uses the
CDBI::Relationship::AssociatedWith module, you'll be able to declare
many-to-many relationships using __PACKAGE__->associated_with(...).  This
method takes the associating class (and optionally the foreign keys and
order_by info, see the University::Student example).  Beside the accessor, the
relationship will also provide "add_to" and "remove_from" methods which will
create/delete corresponding records in the association table.

Sample usage:

---------------------------------------------------------------------
## Base
package University::DBI;
use base 'Class::DBI';
use Class::DBI::Relationship::AssociatedWith;
University::DBI->set_db('Main', 'dbi:ODBC:University');

---------------------------------------------------------------------
## "Class"
package University::Class;
use base 'University::DBI';
__PACKAGE__->table('Classes');
__PACKAGE__->columns(
	All => qw/id title professor/);
__PACKAGE__->has_a(professor => 'University::Professor');
__PACKAGE__->associated_with(students => 'University::Student',
                'University::Signups');

---------------------------------------------------------------------
## "Student"
package University::Student;
use base 'University::DBI';
__PACKAGE__->table('Students');
__PACKAGE__->columns(
	All => qw/id first_name last_name/);
__PACKAGE__->associated_with(classes => 'University::Class',
        {
                association_class => 'University::Signups',
                fkey_this => 'student',
                fkey_that => 'class'
        }
);

---------------------------------------------------------------------
## Association table tying students and classes together
package University::Signup;
use base 'University::DBI';
__PACKAGE__->table('Signups');
__PACKAGE__->columns(
	All => qw/id student class/);
__PACKAGE__->has_a(student => 'University::Student');
__PACKAGE__->has_a(class => 'University::Class');

---------------------------------------------------------------------
## The application code
...
## Get a student's classes
my @classes = $student->classes;

## Associate a class with a student
my $class = University::Class->search(...);
$student->classes->add_to($class);

## Remove a student from a class
$class->students->remove_from($student);
---------------------------------------------------------------------

I'm interested in feedback on the API (class and method names) before I upload
anything to CPAN.

    - Stepan

Working on a many-to-many CDBI::Relationship
Stepan Riha 00:25 on 14 May 2005

Re: Working on a many-to-many CDBI::Relationship
Matt S Trout 11:19 on 14 May 2005

Generated at 15:51 on 25 May 2005 by mariachi v0.52