[Templates] Problem with single element arrays

David david@supaseca.com
Tue, 21 Aug 2007 11:34:39 +1000


This is a multi-part message in MIME format.
--------------050401010406010405020007
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

Hi Andy,

Thanks for the detailed response. Upgrading to the SVN version of 2.20 
has fixed the problem for us.

The 'products' object that we send to the template is a Class::DBI 
database object. The product.images is a has_many relationship between 
the products and images tables in the database. I'm not sure whether 
CDBI returns an array or a reference to an array for has_many 
relationships, and it's not something I would be likely to change in the 
CDBI code anyway, so thankfully the upgrade has done the job.

Thanks again for your help.

Regards,

David

Andy Wardley wrote:
> David wrote:
>> [% product.images.first.filename %]
>
> Hi David,
>
> Is your product.images returning a 'naked' list, like this:
>
>   return @images;
>
> If so, you should consider changing that to return a reference to the 
> list, if possible:
>
>   return \@images;
>
> TT will try and Do The Right Thing in the first case, but it has no 
> way to know what the Right Thing is if you only return one item.  So 
> it leaves it as a single item.  If you return a list ref then you 
> always have a list ref, even if it only contains one item.
>
>> Until the recent upgrade this did work for all instances, but now, if 
>> we have a product that only has one image, the template is treating 
>> it as a scalar object, so 'first' returns an empty object and no 
>> value gets displayed in the template.
>
> What data type are the images?  Are they objects, rather than, say, 
> hash refs?  And if they are objects, are they blessed hashes or 
> something else?
>
> What *should* happen is that a single item is treated as a list and 
> the .first  vmethod is called.
>
> I suspect the problem may have been introduced with a patch to add the 
> full range of 'fallback' vmethods for objects:
>
> #------------------------------------------------------------------------
> # Version 2.14a - 2nd February 2006               ## DEVELOPER RELEASE ##
> #------------------------------------------------------------------------
>
> Stash
> -----
>
> * Activated a patch in Template::Stash from Stephen Howard which adds
>   code for the full set of fallbacks for dot ops called against
>   objects which don't implement the specific method.  For example
>   [% hashobj.vmethod %] [% listobj.2 %] and [% listobj.vmethod %] now
>   all work with the Perl Template::Stash.  Added code to the XS Stash
>   to do the same and updated tests.
>
> It's the only thing I'm aware of that might have affected it.
>
> Hmmm... I just noticed a comment in the section for the as-yet 
> unreleased v2.20:
>
> #------------------------------------------------------------------------
> # Version 2.20 -
> #------------------------------------------------------------------------
>
> * Applied a patch to Template::Stash from Jess Robinson which allows you
>   to call a list method on a single object and have it automatically
>   upgraded to a single item list.  Changed the XS Stash to do the same.
>
>   http://tt2.org/pipermail/templates/2006-November/009115.html
>
> Ah yes, I think this is what you want.  Here's the patch:
>
>   http://template-toolkit.org/svnweb/Template2/revision?rev=1088
>
> And this is the altogether more-gnarly patch I made to do the same 
> thing for the XS Stash:
>
>   http://template-toolkit.org/svnweb/Template2/revision?rev=1090
>
> Ah, OK, now I see why I'm confused.  I'm looking at the SVN version of 
> the Stash code which has been updated.  That's why it looks like it 
> *should* work from where I'm standing (and does, for me at least :-) )
>
> So the first step would be to check it out with the latest version 
> from subversion.
>
>   http://tt2.org/download/index.html#svn
>
> If that works OK then the problem's fixed and I'll push 2.20 out the 
> door RSN.
>
> If that doesn't work, then let me know a bit more about what kind of 
> data structures your images are and we'll try and find out what's 
> going wrong.
>
> Cheers
> A
>

--------------050401010406010405020007
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
  <meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type">
  <title></title>
</head>
<body bgcolor="#ffffff" text="#000000">
<font face="Trebuchet MS">Hi Andy,<br>
<br>
Thanks for the detailed response. Upgrading to the SVN version of 2.20
has fixed the problem for us.<br>
<br>
The 'products' object that we send to the template is a Class::DBI
database object. The product.images is a has_many relationship between
the products and images tables in the database. I'm not sure whether
CDBI returns an array or a reference to an array for has_many
relationships, and it's not something I would be likely to change in
the CDBI code anyway, so thankfully the upgrade has done the job.<br>
<br>
Thanks again for your help.<br>
<br>
Regards,<br>
<br>
David<br>
</font><br>
Andy Wardley wrote:
<blockquote cite="mid:46C999E5.4020900@wardley.org" type="cite">David
wrote:
  <br>
  <blockquote type="cite">[% product.images.first.filename %]
    <br>
  </blockquote>
  <br>
Hi David,
  <br>
  <br>
Is your product.images returning a 'naked' list, like this:
  <br>
  <br>
&nbsp; return @images;
  <br>
  <br>
If so, you should consider changing that to return a reference to the
list, if possible:
  <br>
  <br>
&nbsp; return \@images;
  <br>
  <br>
TT will try and Do The Right Thing in the first case, but it has no way
to know what the Right Thing is if you only return one item.&nbsp; So it
leaves it as a single item.&nbsp; If you return a list ref then you always
have a list ref, even if it only contains one item.
  <br>
  <br>
  <blockquote type="cite">Until the recent upgrade this did work for
all instances, but now, if we have a product that only has one image,
the template is treating it as a scalar object, so 'first' returns an
empty object and no value gets displayed in the template.
    <br>
  </blockquote>
  <br>
What data type are the images?&nbsp; Are they objects, rather than, say,
hash refs? &nbsp;And if they are objects, are they blessed hashes or
something else?
  <br>
  <br>
What *should* happen is that a single item is treated as a list and the
.first &nbsp;vmethod is called.
  <br>
  <br>
I suspect the problem may have been introduced with a patch to add the
full range of 'fallback' vmethods for objects:
  <br>
  <br>
#------------------------------------------------------------------------
  <br>
# Version 2.14a - 2nd February 2006&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ## DEVELOPER RELEASE
##
  <br>
#------------------------------------------------------------------------
  <br>
  <br>
Stash
  <br>
-----
  <br>
  <br>
* Activated a patch in Template::Stash from Stephen Howard which adds
  <br>
&nbsp; code for the full set of fallbacks for dot ops called against
  <br>
&nbsp; objects which don't implement the specific method.&nbsp; For example
  <br>
&nbsp; [% hashobj.vmethod %] [% listobj.2 %] and [% listobj.vmethod %] now
  <br>
&nbsp; all work with the Perl Template::Stash.&nbsp; Added code to the XS Stash
  <br>
&nbsp; to do the same and updated tests.
  <br>
  <br>
It's the only thing I'm aware of that might have affected it.
  <br>
  <br>
Hmmm... I just noticed a comment in the section for the as-yet
unreleased v2.20:
  <br>
  <br>
#------------------------------------------------------------------------
  <br>
# Version 2.20 -
  <br>
#------------------------------------------------------------------------
  <br>
  <br>
* Applied a patch to Template::Stash from Jess Robinson which allows
you
  <br>
&nbsp; to call a list method on a single object and have it automatically
  <br>
&nbsp; upgraded to a single item list.&nbsp; Changed the XS Stash to do the same.
  <br>
  <br>
&nbsp; <a class="moz-txt-link-freetext" href="http://tt2.org/pipermail/templates/2006-November/009115.html">http://tt2.org/pipermail/templates/2006-November/009115.html</a>
  <br>
  <br>
Ah yes, I think this is what you want.&nbsp; Here's the patch:
  <br>
  <br>
&nbsp; <a class="moz-txt-link-freetext" href="http://template-toolkit.org/svnweb/Template2/revision?rev=1088">http://template-toolkit.org/svnweb/Template2/revision?rev=1088</a>
  <br>
  <br>
And this is the altogether more-gnarly patch I made to do the same
thing for the XS Stash:
  <br>
  <br>
&nbsp; <a class="moz-txt-link-freetext" href="http://template-toolkit.org/svnweb/Template2/revision?rev=1090">http://template-toolkit.org/svnweb/Template2/revision?rev=1090</a>
  <br>
  <br>
Ah, OK, now I see why I'm confused.&nbsp; I'm looking at the SVN version of
the Stash code which has been updated.&nbsp; That's why it looks like it
*should* work from where I'm standing (and does, for me at least :-) )
  <br>
  <br>
So the first step would be to check it out with the latest version from
subversion.
  <br>
  <br>
&nbsp; <a class="moz-txt-link-freetext" href="http://tt2.org/download/index.html#svn">http://tt2.org/download/index.html#svn</a>
  <br>
  <br>
If that works OK then the problem's fixed and I'll push 2.20 out the
door RSN.
  <br>
  <br>
If that doesn't work, then let me know a bit more about what kind of
data structures your images are and we'll try and find out what's going
wrong.
  <br>
  <br>
Cheers
  <br>
A
  <br>
  <br>
</blockquote>
</body>
</html>

--------------050401010406010405020007--