Re: Access to has_a data from Template?
[prev]
[thread]
[next]
[Date index for 2004/09/17]
On Thu, Sep 16, 2004 at 07:31:11PM -0400, Charles Bailey wrote:
> --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.
[...]
> 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.
And in a message that was bounced from the list, but which he
then sent privately, Jason Kohles wrote:
> It sounds to me like Jesse has a class that includes something like
> this:
> package MyLibrary::Book;
> ...
> MyLibrary::Book->has_a(format => 'MyLibrary::Book::Format');
>
> and now wants to take this, and knowing only that books are represented
> by the MyLibrary::Book class, and that they have a format relationship,
> wants to determine the class that the format will be inflated to.
>
> If I'm understanding the problem correctly, you can do this.
> [...]
>
> package main;
> use MyLibrary::Book;
>
> print "format is a ".MyLibrary::Book->__hasa_rels->{format}."\n";
Thank you very much to both Charles and Jason for figuring out what
I was trying to do and showing some ways of getting there.
In the meantime, I also looked at the guts of Simon Cozens'
Class::DBI::AsForm, and he shows a similar way of getting the
necessary information. For example, here's his way of getting
a "select" list from a has_a reference (there's earlier code
doing the whole "ref" thing to see is something is a
relationship, as Charles showed in an unquoted section; this
is once you've decided you want a select) (also, this is
lightly edited, and from an earlier version; the current
version uses HTML::Element objects which confuse the point I'm
trying to make):
sub _to_select {
my ($self, $col) = @_;
my $has_a_class = $self->__hasa_rels->{$col}->[0];
my @objs = $has_a_class->retrieve_all;
my $sel = -1;
if (ref $self and $self->$col()) { $sel = $self->$col()->id }
my %labels = map { $_->id => "".$_ } @objs;
return CGI::popup_menu( -name => $col,
-values => [ map {$_->id} @objs ],
-default => $sel,
-labels => \%labels );
}
This is pretty much exactly what I'm trying to do.
I see that __hasa_rels, which Jason also used, is deprecated
in favor of meta_info, but meta_info isn't documented in the
docs for .96. Perhaps this could be remedied. Then I can
try writing something like the above but with the approved
methods.
Best,
Jesse Sheidlower