Re: Access to has_a data from Template?
[prev]
[thread]
[next]
[Date index for 2004/09/16]
--On Thursday, September 16, 2004 3:19 PM -0400 Jesse Sheidlower
<jester@xxxxx.xxx> wrote:
>
> Let me put it another way: given that I have a book object,
> and that I know book has_a format, is there any way I can get
> a format object? Without necessarily knowing that my format
> class is MyLibrary::Book::Format? Can I get there from a
> book object?
I apologize if I'm belaboring the obvious, but it seems much of the
confusion in this thread is revolving around the distinction between object
and class attributes.
If you have a book object (:= an instance of Book, say "Moby Dick"), you
can get its format, and because of the has_a get a Book::Format object
back, on which you can operate:
my $format = $moby->format;
if ($format->genre eq 'Novel' and $format->binding eq 'Hardcover') {
. . .
}
However, if you want to ask whether the _class_ Book has an attribute named
"format", and what properties that attribute might have, you can't get
there by retrieving a "format" attribute of the class. You can ask the
class what the attributes of its objects are:
my @attr = Book->columns;
(Note that this gives you the DB-level attributes Class::DBI knows about.
If you've defined custom accessors for other non-DB "attributes" in your
class, you'd need to grovel over the class's symbol table to discover them.)
You can also find out if Book has any columns linked by relationships to
other objects:
my $hasa_info = Book->meta_info('has_a');
while (my($col,$specs) = each %$hasa_info) {
print "$col points to a ",$specs->foreign_class,"\n";
}
# . . . similarly for has_many and might_have
and finally, you can find out what the attributes of the foreign_class are
as described above.
As a bit of a shortcut (and a little insurance against changes in the
format of the class's meta_info with future versions of CDBI), if you know
a particular book exists (and all its attributes are defined), you can do
something like
my $book = Book->retrieve($book_id);
foreach my $col (Book->columns) {
my $attr = $book->$col;
if (ref $attr) { # Must have been a (?:might_)?ha(:?ve|s)_?(?:many)?
deal_with_object_attr_here($attr);
}
else {
deal_with_simple_attr_here($attr);
}
}
As a last point, it sounds like you wanted to retrieve the potential values
of an (enumerated, I'd guess) attribute for presentation to the user.
That'll require one of three things:
- (expensive) retrieve_all and tabulating the values, or
- a custom SQL "SELECT DISTINCT", or
- a call to enum_vals (if you're using C::D::MySQL or similar).
The first two will return a set of legal values, which may be a subset of
the allowed values. The last will return the set to which the DB
constrains the column; if you've got a CDBI-level constraint, you won't
hear about it here.
All told, if you control the entire system, it's probably fastest and
easiest to keep track of the possibilities yourself and send them along to
the template. If hard-coding them grates, perhaps you can track your own
set of class-level metadata and pass that along to the template in a more
generic way.
I hope this helps.
--
Regards,
Charles Bailey < bailey _at_ newman _dot_ upenn _dot_ edu >
Newman Center at the University of Pennsylvania
|
(message missing)
|