[Vienna-pm] Re: Class::DBI pod/doc issues and question for m2m +might_have

matthias tarasiewicz parasew at sonance.net
Tue Sep 30 16:23:04 CDT 2003


perrin,
i hope it's not a problem, but i thought it might be nice to reply to 
the whole list instead just to you personally.
i finally have the answers to my problems/questions.
for reference, i attached all the important information from the last 
mail with my question.

Perrin Harkins wrote:
 > On Tue, 2003-09-30 at 14:43, matthias tarasiewicz wrote:
 >
 >>package FsDBI::User;
 >>   use base ('FsDBI');
 >>   __PACKAGE__ ->table    ('user');
 >>   __PACKAGE__ ->columns  (Essential => qw(id accountname firstname
 >>lastname) );
 >>   __PACKAGE__ ->has_many (thisismyrole=> ['FsDBI::User::RoleRef' =>
 >>'role_id']);
 >
 >
 > You normally need to give an extra argument to has_many that tells it
 > which column of the FsDBI::User::RoleRef class to look in.   You can
 > leave this out when that column has the same name as the current class
 > (i.e. "user"), but in this case it doesn't.
 >
 > __PACKAGE__->has_many (thisismyrole=> ['FsDBI::User::RoleRef' =>
 > 'role_id'], 'user_id');
 >
 > - Perrin

thank you very much. this was the information i was missing to get this 
running. this is definitely missing in the POD of Class::DBI!

finally, the follwing was working for my script

#!/usr/bin/perl

use FsDBI;

# retrieve user with id=1
my $test=FsDBI::User->retrieve(1);
print "user ".$test->accountname."\n";

# cycle through all the entries the user has
# and print the diz-field of the entries
foreach my $fugu ($test->UserRoles)
{
   print $fugu->diz;
   print "\n";
}


Perrin Harkins wrote:
> matthias tarasiewicz wrote:
>> for having a good usage of Class::DBI, as far as i understood it you 
>> have to reference the classes the way you want to use them.
>> this means that the has_a and has_many does not need to be the same as 
>> your references in the database.
> 
> These will only work if you actually have the references in the 
> database.  All they do is issue SQL queries, so your cd table has to 
> have a column holding an artist ID in order for your artist class to do 
> a has_many cds.  If you're saying that it's not necessary to turn every 
> single foreign key into a has_a or has_many, then I agree. 

this is what i actually meant.

> Writing good documentation is hard and takes a lot of time.  I think the 
> Class::DBI docs are quite good.  Adding some example SQL tables to go 
> along with the music examples in the synopsis sounds like a good idea. I 
> think the music example is better than the user/role stuff in your 
> examples at the end, because it's more universal.
> 

yes, that's a good thing to put the underlying database in the pod, 
since things confused me a lot in those examples.
my tables where more to illustrate you my problems, no suggestions for 
becoming part of the documentation ;)

>> issues like correct naming of Classes and database-tables become a 
>> problem
> 
> 
> I'm not sure what you mean by this.  You can use any class or table name 
> you like.
> 

see above, i had problems with the mapping as described in the pod since 
i did not know much about the database-table names...


> The many-to-many example in the documentation works like this:
> 
> 1) Create classes for a CD table, a STYLE table, and a CD_STYLE table 
> linking them together.
> 
> 2) In your CD class, say it has_many CD_STYLES.
> 
> 3) In your CD_STYLES class, say it has_a STYLE.
> 
> That's it.  Then you can do this:
> 
>         sub styles {
>                 my $self = shift;
>                 return map $_->STYLE, $self->CD_STYLES;
>         }
> 
> Or you can abbreviate that like this:
> 
>        Music::CD->has_many(STYLES => [ 'CD_STYLE' => 'STYLE' ]);
> 
> The might_have work just like has_a, but it can also import some fields 
> from the other object.
> 

this plus the last mail you sent me (see above) definitely should go in 
the POD! very important since this was the reason why i was mingling 
with data for hours (not to say days)

> I agree, a many-to-many method would be useful.  If you'd like to try 
> writing one, look at the has_many method.

uh, i think this might take some time until i'm ready for that ... ;)


>> for has_a compared to has_many i found it strange that one is 
>> depending on correct naming (has_a), the other one completely not.
> 
> has_a doesn't depend on naming.  You tell it the name of the accessor in 
> the current class, and the name of the class to create.  They can have 
> any names you want.  It assumes that the accessor you specify will 
> return a value that can be used as the primary key on the class.
> 

to some point, it depends on naming (as far as i can tell)
if we take the example you posted on perlmonks
http://perlmonks.org/index.pl?node_id=295176

you have to create a sub for using a has_a with another accessor name 
than the key

sub accessor_name {
     my ($class, $column) = @_;
     $column =~ s/role_id/wild_and_crazy_role/;
     return $column;
}

while in has_a you can call the accessor anything you want, because of 
the additional argument you can pass:
__PACKAGE__ ->has_many(ihavesomuchroles => 'MyPackage::role','id');

where 'id' would be the id from MyPackage::role

>> # ???
>> #  FsDBI::User ->has_many (Roles  => ['FsDBI::User::user_role' => 
>> 'role_id']);
> 
> 
> Yes.
> 
>> #???
>> #  FsDBI::User::user_role ->has_many(Users    =>'FsDBI::User','id');
> 
> 
> No, has_a, not has_many.  This one is not needed if you just want to set 
> up $user->roles().
> 
>> #  FsDBI::User::user_role ->has_many(Roles    =>'FsDBI::User::Role', 
>> 'id');
> 
> 
> No, has_a again.
> 
> - Perrin


thanks for all the help and greetings,
matthias

--
that's the way i like I.T.
http://fs2.at
-------------- next part --------------
perrin,
first of all thanks for your reply on my first mail.

i am trying for hours now to understand the m:m mapping, but still don't get it running. maybe you can take a look as i am completely lost:


# i have still problems with m:m (many to many) mapping and Class::DBI
# http://search.cpan.org/~tmtm/Class-DBI-0.94/lib/Class/DBI.pm#Mapping

#in a nearby script i call like this

use FsDBI;
my $test=FsDBI::User->retrieve(1);
my @gugu= $test->thisismyrole;


# i always get the error
# Use of 'croak' is deprecated at /usr/lib/perl5/site_perl/5.8.0/Class/DBI.pm line 950.
# Use '_croak' instead is not a column of FsDBI::User::roleref at ./test.pl line 7


# i have this SQL (mysql)
#
# CREATE TABLE user (
# id        mediumint(7)  NOT NULL auto_increment,
# firstname     varchar(25) NOT NULL,
# PRIMARY KEY (id),
# ) Type=MyISAM;
#
# CREATE TABLE user_role (
# entry_id    mediumint(7) NOT NULL,
# user_id        mediumint(7) NOT NULL,
# role_id        smallint(6) NOT NULL,
# ) Type=MyISAM;
#
#
# CREATE TABLE role (
# id        smallint(6) NOT NULL auto_increment,
# title        varchar(50) NOT NULL,
# diz        varchar(50) NOT NULL,
# PRIMARY KEY (id)
# ) Type=MyISAM;
#
# CREATE TABLE entry (
# id        mediumint(7) NOT NULL auto_increment,
# txt        text,
# PRIMARY KEY (id)
# ) TYPE=MyISAM;default NULL,


# so i am wondering how to make a m:m mapping at least to get
# the roles a user would have.
# i didn't suceed yet.


 require DBD::mysql;
  use strict;
  use warnings;
  #require Class::DBI::mysql;

  use vars qw($VERSION);
  $VERSION = '0.1b';

package FsDBI;
  use base ('Class::DBI');
  FsDBI->set_db('Main', 'DBI:mysql:dbname', 'user', 'pass');

package FsDBI::User;
  use base ('FsDBI');
  __PACKAGE__ ->table    ('user');
  __PACKAGE__ ->columns  (Essential => qw(id accountname firstname lastname) );
  __PACKAGE__ ->has_many (thisismyrole=> ['FsDBI::User::RoleRef' => 'role_id']);


package FsDBI::User::RoleRef;
  use base ('FsDBI');
  __PACKAGE__ ->table  ('user_role');
  __PACKAGE__ ->columns(Essential => qw(user_id role_id));
  __PACKAGE__ ->has_a  (role_id  =>'FsDBI::User::Role');
  __PACKAGE__ ->has_a  (user_id  =>'FsDBI::User');

package FsDBI::User::Role;
  use base ('FsDBI');
  __PACKAGE__ ->table  ('role');
  __PACKAGE__ ->columns(Essential  => qw( id title diz)); 


More information about the Vienna-pm mailing list