Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Template module output wrong, very odd! 1

Status
Not open for further replies.

1DMF

Programmer
Joined
Jan 18, 2005
Messages
8,795
Location
GB
I have this code
Code:
# set time
my $time = time;

# Get Charts
my @rs = &getSQL("Charts","UserID,Title,Genre,Info,Plays,Votes,Rank,Best","1=1","Votes DESC");
[b]
for(my $x=1; $x<=39; $x++){
    $rs[$x] = $rs[0];
}
[/b]

# Set Rank Counter
my $rnk = 0;
my $rcol = 0;

# Loop chart records
	for(@rs) {
        
        my $newt = "";
        $rcol++;

        # Get Status Info
        my @stat = &getSQL("Status","TStamp","UserID='$_->{'UserID'}'");

        # Work week to show if new
        my $newtune1 = $stat[0]{'TStamp'} + 604800;  # 7 days in seconds
        my $newtune2 = $stat[0]{'TStamp'} + 2419200; # 28 days in seconds
        
        if($newtune1 > $time){$newt = " style=\"color:#00EE00;\" ";}
        elsif($newtune2 < $time){$newt = " style=\"color:#FFCC66;\" ";}

			# Add 1 to rank counter
			$rnk++;
     
			# Build chart output
            my $javaTitle = $_->{'Title'};
            $javaTitle =~ s/'/\\'/g;
            
            $_->{'JavaTitle'} = $javaTitle;

            $_->{'Pos'} = $rnk;

            $_->{'TuneCol'} = $newt;

            $_->{'RowCol'} = $rcol;

            if($rcol == 1){$_->{'RowCol'} = "#f5fafa";}
            else{$_->{'RowCol'} = "#ffffff"; $rcol = 0;}
	}

# Start template 
my $template = HTML::Template->new(  global_vars => 1,
                                            type => 'filename',
                                          source => DIR_TO_CGI . '/templates/top40.tp',
                               die_on_bad_params => 0) or die "Cannot open top40.tp Template file: $!";

# Add global variables to Template
$template->param( 'url_to_domain' => URL_TO_DOMAIN );
$template->param( 'url_to_cgi' => URL_TO_CGI );
$template->param( 'charts' => \@rs );

# Print Template    
print "Content-type: text/html\n\n";
print $template->output; 
exit();
the part in bold I have added just to create some extra dummy records, this all works fine.

However when i display the results I get this..

40 / 1 dj-c.d.c. Only Love (Set Us Free) Dancecore 5 2 Play / Info / Vote
40 / 1 dj-c.d.c. Only Love (Set Us Free) Dancecore 5 2 Play / Info / Vote
40 / 1 dj-c.d.c. Only Love (Set Us Free) Dancecore 5 2 Play / Info / Vote
40 / 1 dj-c.d.c. Only Love (Set Us Free) Dancecore 5 2 Play / Info / Vote
40 / 1 dj-c.d.c. Only Love (Set Us Free) Dancecore 5 2 Play / Info / Vote
up to 40 records which is correct however the first number 40 is wrong, this should be 1,2,3,4 etc...

and if you look @ the code where I add $_->{'Pos'} = $rnk; you will see I'm doing the simple increment and adding it to the template var.

If in the code I get it to print out $_->{'Pos'} it shows 1,2,3,4 etc.. as expected but the tmpl_loop is not showing each record.

Is this a bug in the template module? why am I getting this strange result when the code and all debuging shows the correct data.

many thanks, 1DMF



"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you.
 
Code:
$_->{'RowCol'} = $rcol;

            if($rcol == 1){$_->{'RowCol'} = "#f5fafa";}
            else{$_->{'RowCol'} = "#ffffff"; $rcol = 0;}
You seem to be setting RowCol twice. Is this a typo?

Steve

[small]"Every program can be reduced by one instruction, and every program has at least one bug. Therefore, any program can be reduced to one instruction which doesn't work." (Object::PerlDesignPatterns)[/small]
 
yup, lol

but apart from that stupid mistake why on earth is it not showing $rnk in the ->{'Pos'} variable?

"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you.
 
Because of the way you're setting it up I think.

@rs is an array of hashes, right?

The thing to remember is that it's actually technically impossible to have an array of hashes, despite what we usually call them. What you actually have is an array of *references* to hashes, which is just different enough to cause you headaches.

This code:
Code:
for(my $x=1; $x<=39; $x++){
    $rs[$x] = $rs[0];
}
I assume your GetSQL subroutine is only returning one row of data. Now you're trying to copy that data into 39 more rows. However, instead of copying the data itself, you're copying a *reference* to the data (the hash). So this means that you now have an array of 40 references that all point to the same hash! This is why you're seeing all the counter being 40: every time you set 'Pos', you're changing it for all elements in @rs, since they're technically the same.
 
Post the template?

Steve

[small]"Every program can be reduced by one instruction, and every program has at least one bug. Therefore, any program can be reduced to one instruction which doesn't work." (Object::PerlDesignPatterns)[/small]
 
Oooh. Good spot ishnid. We are not worthy...

Steve

[small]"Every program can be reduced by one instruction, and every program has at least one bug. Therefore, any program can be reduced to one instruction which doesn't work." (Object::PerlDesignPatterns)[/small]
 
Ishnid is a god!

"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you.
 
ok so why can't I do this....

Code:
for(my $x=1; $x<=39; $x++){
    my %tst = \$rs[0]
    push @rs, %tst;
}

I want to create an on the fly hash %tst, which is the actual hash of $rs[0] and then push that into @rs, thus creating a new hash reference each loop and shoving that into the array.

In theory it should work shouldn't it, but I'm getting an error....
Global symbol "%tst" requires explicit package

now i thought i'd declared it with the my each loop but obviously i'm doing something stupid!

how do I make it push the dereferenced data into a new hash and then push that into the array?

"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you.
 
You should have another error before the "Global symbol" one. That's triggered by the fact that the line above it is a syntax error. You're getting a reference to the reference stored in $rs[0] and then trying to save it as a hash.

A relatively painless way to do this is to use the Clone module:
Code:
# at the top
use Clone qw(clone);

# then later on
push @rs, clone( $rs[0] );

I'm not sure about being a god - thanks for the star though :-)
 
once again the TT Perl Guru saves the day :-)

What colour is your cape ishnid? [batman]

"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you.
 
agghhh - clone isn't installed on the server and I can't open tar files.

any chance someone can email me the clone.pm

bollax(at)hotmail(dot)com

thanks
1DMF

"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you.
 
Clone isn't a pure Perl module so just copying the .pm file won't do it. Is the "Storable" module present on the server. You can use its "dclone" function in exactly the same way. It's a bit slower apparently, but it's better than not having it at all!
 
tell you what for this requirement i'm going to use
Code:
push @rs, {UserID => $rs[0]{'UserID'}, Title => etc..

it's a lot easier :-)

"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you.
 
If that doesn't work, you could just use this line:
Code:
push @rs, { map { $_ => $rs[0]->{$_} } keys %{$rs[0]} };

There are probably nicer ways to do it, but that should be ok for this task. Of course, it's not recursive so if the hash referenced by $rs[0] has references contained inside it, this won't work as you want. That's the advantage of using Clone or Storable.
 
I'm such an overcomplicated idiot sometimes:
Code:
push @rs, { %{$rs[0]} };
That's the one!
 
IC, as always you're a gent ishnid.

As you already observed it's an array of hashes as a record set , so it is raw data in the hash not any references.

thanks for the help
1DMF

"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you.
 
you know the more I look at the final bit, i'm thinking the same thing to myself, d'oh, idiot!

sometimes things are just too obvious!

I knew I wanted to dereference the hash and push it back into the array.

Good job ishnid.

"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top