[Maypole] the subtleties of many-to-many stringification

Seth Gordon sethg@ropine.com
Thu, 02 Dec 2004 15:20:12 -0500


Work on my Maypolized library database is continuing apace, but I'm 
confused by a certain detail.

My database has a "titles" table, an "authors" table, and a 
"title_author_rel" table linking the two:

CREATE TABLE title_author_rel (
     title_id integer,
     author_id integer,
     relationship character(6) DEFAULT 'by'::bpchar
         -- 'by', 'ed.', 'trans.', etc.
);

I set up the relationship in my application package...

package JeevesLibrary;
#...
JeevesLibrary::TitleAuthorRel->has_a(title_id => 'JeevesLibrary::Titles');
JeevesLibrary::TitleAuthorRel->has_a(author_id => 'JeevesLibrary::Authors');

JeevesLibrary::Titles->has_many(authors =>
     [ JeevesLibrary::TitleAuthorRel => author_id ]);
JeevesLibrary::Authors->has_many(titles =>
     [ JeevesLibrary::TitleAuthorRel => title_id ]);


...and everything Just Worked, except for one small detail: the 
"authors" list on the ...library/titles/view/#### page just has the 
authors' names, and not the relationships.

I can make the list show relationships by changing the many-to-many 
relationship and defining how to stringify title_author_rel:

package JeevesLibrary;
#...
JeevesLibrary::Titles->has_many(authors => 'JeevesLibrary::TitleAuthorRel');
# ...
# ...
package JeevesLibrary::TitleAuthorRel;
#...
sub stringify_self {
     my $self = shift;
     return $self->relationship . ' ' . $self->author_id;
}

This makes the names in the authors list show up a "by Smith" instead of 
just "Smith", but then the links take me to a title_author_rel/view/### 
page instead of an author_view/### page.

I tried adding a view method to JeevesLibrary::TitleAuthorRel that would 
  look up the appropriate author object and swap it in (an object 
switcheroo rather than the template switcheroo), but
When I try to add a "sub view :Exported {}" method to one of my model 
packages, my module gets a compilation error:

Couldn't require JeevesLibrary - Invalid CODE attribute: Exported at 
/home/sethg/bin/JeevesLibrary.pm line 106

Well, *that*'s damn strange.

I worked around this by overriding the process method in 
JeevesLibrary::TitleAuthorRel:

sub process {
     my ($class, $r) = @_;
     my $method = $r->action;
     return if $r->{template};
     $r->{template} = $method;
     $r->objects( [] );
     my $tar = $class->retrieve($r->{args}->[0]);
     if ($tar) {
         my $author = $tar->author_id;
         $r->objects( [$author] ) if $author;
     }
     $r->model_class('JeevesLibrary::Authors');
     $r->{template_args}{title} =
         ' author / ' . $r->config->application_name;
     JeevesLibrary::Authors->$method($r, $author, @{ $r->{args} } );
}

This seems to work, but I am still wondering

(a) why I can't add :Exported methods, dammit
(b) if there is a more elegant way to do the same thing

-- 
// seth gordon // sethg@ropine.com // http://dynamic.ropine.com/yo/ //