Re: Cross between MightHave and HasMany?
[prev]
[thread]
[next]
[Date index for 2004/11/02]
On Tue, 2 Nov 2004 16:35:02 -0500, Kingsley Kerce
<kingsley@xxxxxxxxxxxxxxxx.xxx> wrote:
> Jess Robinson writes:
> > On Tue, 2 Nov 2004 15:08:47 -0500, Kingsley Kerce
> > <kingsley@xxxxxxxxxxxxxxxx.xxx> wrote:
> >
> > > Jess Robinson writes:
> > > > Hi folks,
> > > >
> > > > I have a setup similar to:
> > > >
> > > > create table person (
> > > > personid int primary key auto_increment,
> > > > firstname varchar(32),
> > > > initials varchar(16),
> > > > surname varchar(64),
> > > > date_of_birth datetime
> > > > );
> > > >
> > > > create table categories (
> > > > catid int primary key auto_increment,
> > > > category varchar(128)
> > > > );
> > > >
> > > > create table personcategories (
> > > > personid int,
> > > > catid int
> > > > );
> > > >
> > > > So I've been looking for a way to say 'person might have a
> category,
> > > via
> > > > table personcategories', I can't see way to do it using existing
> > > > relationship types, or am I missing something? Essentially I'd
> like
> > > > $person->category() and $person->category($catobj) to do the
> right
> > > thing.
> > >
> > > It seems as if a many-to-many would serve you fine.
> > > First, rename your last two tables to 'category' and
> 'personcategory'.
> > > Then set up a many-to-many as follows (code untested).
> > > PersonCategory->has_a(personid => 'Person');
> > > PersonCategory->has_a(catid => 'Category');
> > > Person->has_many(categorys => [ 'PersonCategory' => 'catid' ]);
> > > Category->has_many(persons => [ 'PersonCategory' => 'personid' ]);
> >
> > This is actually what Im currently doing, its just slightly annoying
> to
> > have to remember that it will return a list, and I need to grab the
> first
> > item from that list. Since a person can only be in one category at
> once.
> > (At least in my scenario ,)
>
> To abstract away the annoyance, put a category() method in the Person
> package:
>
> package Person;
> ...
> sub category {
> my $self = shift;
>
> my ($category) = $self->categorys;
> return $category;
> }
Thats an idea, thanks.
>
> > > Now you can use
> > >
> > > my $person = Person->retrieve(1);
> > > foreach my $category ($person->categorys) {
> > > ...
> > > }
> > > # or if in your scenario you know a person will only be in one
> category
> > > my ($category) = $person->categorys;
> > > ...
> > >
> > > # your "might have" requirement is satisfied, as
> $person->categorys
> > > # will yield nothing if a person has no category
> >
> > > Not sure what you're after when you say: $person->category($catobj)
> >
> > To be able to pass in a category object to $person->category and have
> it
> > update PersonCategories as appropriate.. At the moment I'm first
> deleting
> > any rows in there that contain that person_id, and then adding the
> new one.
>
> That's what the CDBI add_to_*() methods are for.
>
> $person->add_to_categorys({
> catid => $catobj->id,
> });
>
> The above will insert a row into PersonCategory.
Well yes, but it wont observe the 'one person, one category' rule, will
it? And thus get rejected by my constraint, which says the personid is the
primary key.
> Alternatively, I suppose you could adjust the above category() method,
> as follows, but add_to_categorys() seems just fine.
>
> sub category {
> my $self = shift;
> my $catobj = shift;
>
> if ($catobj) {
> # do the update here to your liking...
> }
>
> my ($category) = $self->categorys;
> return $category;
> }
'Update', mmm that gives me an idea, I wonder.. If I get the
PersonCategory object, and just change its categoryid, whther that will
update as required..
Jess
>
> Kings
>
> > >
> > > >
> > > > Also I'd like to be able to remove the relationship, without
> deleting
> > > > either the person or the category themselves.
> > > >
> > > > Any ideas?
> > > >
> >
> >
> > Jess
>
>
--
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/