Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Catalyst - Model Data Not Rendering in TT Template

by roho (Chancellor)
on Mar 16, 2010 at 00:56 UTC ( #828813=perlquestion: print w/replies, xml ) Need Help??

roho has asked for the wisdom of the Perl Monks concerning the following question:

Environment:

  • Windows Vista
  • Activestate Perl 5.8.9 (build 827)
  • Catalyst 5.8002
  • DBIx::Class 0.08120
  • Template Toolkit 2.22
  • SQLite 3.6.23

Problem:
I am working through the examples in Chapter 2 of Jonathan Rockway's book "Catalyst: Accelerating Perl Web Application Development". I completed the code for the 'database' example, but when I open it in my browser I get over 200 lines of debug information (see "Web Page Output" below).

I have included the "Model", "View", "Controller", and "Schema" packages, and the "TT" template generated by Catalyst for completeness, but the problem appears to be between the "Controller" package, which contains the subroutine 'list_messages' to retrieve and stash data from SQLite, and the TT template, based on the error message displayed on the web page: Couldn't render template "list_messages.tt"

I have independently tested the SQLite database in a standalone Perl program using DBD::SQLite and it is working properly. Any ideas on what is preventing the template from rendering the model data? TIA

Model
package MyApp::Model::TestDatabase; use strict; use base 'Catalyst::Model::DBIC::Schema'; __PACKAGE__->config( schema_class => 'MyApp::Schema::TestDatabase', connect_info => { dsn => 'dbi:SQLite:\tmp\database', user => '', password => '', } ); =head1 NAME MyApp::Model::TestDatabase - Catalyst DBIC Schema Model =head1 SYNOPSIS See L<MyApp> =head1 DESCRIPTION L<Catalyst::Model::DBIC::Schema> Model using schema L<MyApp::Schema::T +estDatabase> =head1 GENERATED BY Catalyst::Helper::Model::DBIC::Schema - 0.4 =head1 AUTHOR A clever guy =head1 LICENSE This library is free software, you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1;

View
package MyApp::View::TT; use strict; use warnings; use base 'Catalyst::View::TT'; __PACKAGE__->config( TEMPLATE_EXTENSION => '.tt', render_die => 1, ); =head1 NAME MyApp::View::TT - TT View for MyApp =head1 DESCRIPTION TT View for MyApp. =head1 SEE ALSO L<MyApp> =head1 AUTHOR A clever guy =head1 LICENSE This library is free software. You can redistribute it and/or modify it under the same terms as Perl itself. =cut 1;

Controller
package MyApp::Controller::Database; use strict; use warnings; use parent 'Catalyst::Controller'; =head1 NAME MyApp::Controller::Database - Catalyst Controller =head1 DESCRIPTION Catalyst Controller. =head1 METHODS =cut =head2 index =cut sub list_messages :Path :Args(0) { my ( $self, $c ) = @_; $c->stash->{template} = 'list_messages.tt'; $c->stash->{messages} = $c->model('TestDatabase::test'); } =head1 AUTHOR A clever guy =head1 LICENSE This library is free software. You can redistribute it and/or modify it under the same terms as Perl itself. =cut 1;

Schema
package MyApp::Schema::TestDatabase; # Created by DBIx::Class::Schema::Loader # DO NOT MODIFY THE FIRST PART OF THIS FILE use strict; use warnings; use base 'DBIx::Class::Schema'; __PACKAGE__->load_namespaces; # Created by DBIx::Class::Schema::Loader v0.05003 @ 2010-03-15 17:04:1 +2 # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:JXK2KkfO7oQ7utxuHZbjpg # You can replace this text with custom content, and it will be preser +ved on regeneration 1;

TT Template
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <title>Hello, database!</title> </head> <body> <h1>Database</h1> <p>Here's what the database looks like: </p> <ol> [% WHILE (message = messages.next) %] <li> <p>Message <b>[% message.subject | html %]</b> (#[% message.id | html %]):</p> <p>[% message.message | html %]</p> <p>Written at <i>[% message.date | html %]</i>.</p> </li> [% END %] </ol> </body> </html>

Web Page Output
MyApp on Catalyst 5.8002 Couldn't render template "list_messages.tt" Request bless({ _path => "database", action => "database", address => "192.168.1.102", arguments => [], base => bless(do{\(my $o = "http://localhost:3000/")}, " +URI::http"), body_parameters => {}, captures => [], cookies => {}, headers => bless({ "accept" => "*/*", "accept-encoding" => "gzip, deflate", "accept-language" => "en-us", connection => "Keep-Alive", host => "localhost:3000", "user-agent" => "Mozilla/4.0 (compatible; MSIE + 8.0; Windows NT 6.0; WOW64; Trident/4.0; SLCC1; .NET CLR 2.0.50727; +Media Center PC 5.0; InfoPath.2; .NET CLR 3.5.30729; .NET CLR 3.0.307 +29; OfficeLiveConnector.1.4; OfficeLivePatch.1.3)", }, "HTTP::Headers"), match => "database", method => "GET", parameters => {}, protocol => "HTTP/1.0", query_parameters => {}, remote_user => undef, secure => 0, uploads => {}, uri => bless(do{\(my $o = "http://localhost:3000/databa +se")}, "URI::http"), user => undef, }, "Catalyst::Request") Response bless({ body => "", cookies => {}, finalized_headers => 0, headers => bless({ "content-type" => "text/html; charset=utf-8", "x-catalyst" => "5.8002", }, "HTTP::Headers"), status => 200, }, "Catalyst::Response") Stash do { my $a = { messages => bless({ _attrs => { alias => "me", as => ["id", "subject", "message", "date"], collapse => {}, from => [ { "-alias" => "me", "-source_handle" => bless({ schema => bless({ class_mappings => { "MyApp::Model::TestD +atabase::Test" => "Test", "MyApp::Schema::Test +Database::Result::Test" => "Test", }, source_registrations => { Test => bless({ _columns => { date => +{ _i +nflate_info => { deflate => sub { "???" }, inflate => sub { "???" } } +, da +ta_type => "DATETIME", de +fault_value => undef, ex +tra => {}, is +_nullable => 1, si +ze => undef, }, id => { da +ta_type => "INTEGER", de +fault_value => undef, ex +tra => {}, is +_nullable => 1, si +ze => undef, }, message +=> { da +ta_type => "TEXT", de +fault_value => undef, ex +tra => {}, is +_nullable => 1, si +ze => undef, }, subject +=> { da +ta_type => "TEXT", de +fault_value => undef, ex +tra => {}, is +_nullable => 1, si +ze => undef, }, }, _columns_info_ +loaded => 0, _ordered_colum +ns => ["id", "subject", "message", "date"], _primaries => +["id"], _relationships + => {}, _unique_constr +aints => { primary => 'fix' }, name => "Test" +, result_class = +> "MyApp::Model::TestDatabase::Test", resultset_attr +ibutes => {}, resultset_clas +s => "DBIx::Class::ResultSet", schema => 'fix +', source_name => + "Test", sqlt_deploy_ca +llback => "default_sqlt_deploy_hook", }, "DBIx::Class: +:ResultSource::Table"), }, storage => bless({ _conn_pid = +> 4448, _connect_info = +> [ + { dsn => "dbi:SQLite:\\tmp\\database", password => "", user => "" + }, + ], _dbh = +> bless({ + # tied DBI::db + }, "DBI::db"), _dbh_autocommit = +> 1, _dbh_gen = +> 0, _dbi_connect_info = +> [ + "dbi:SQLite:\\tmp\\database", + "", + "", + { AutoCommit => 1, PrintError => 0, RaiseError => 1 }, + ], _driver_determined = +> 1, _in_dbh_do = +> 0, _sql_maker = +> bless({ + _cached_syntax => "LimitOffset", + array_datatypes => 1, + bindtype => "columns", + "cmp" => "=", + equality_op => qr/^(\=|is|(is\s+)?like)$/i, + from_bind => [], + having_bind => [], + inequality_op => qr/^(!=|<>|(is\s+)?not(\s+like)?)$/i, + limit_dialect => "LimitOffset", + logic => "OR", + order_bind => [], + special_ops => [ + { handler => "_where_field_BETWEEN", regex = +> qr/^(not )?between$/i }, + { handler => "_where_field_IN", regex => qr/ +^(not )?in$/i }, + ], + sqlfalse => "0=1", + sqltrue => "1=1", + unary_ops => [ + { handler => "_where_op_ANDOR", regex => qr/ +^and (?: \s? \d+ )? $/ix }, + { handler => "_where_op_ANDOR", regex => qr/ +^or (?: \s? \d+ )? $/ix }, + { handler => "_where_op_NEST", regex => qr/^ +nest (?: \s? \d+ )? $/ix }, + { handler => "_where_op_BOOL", regex => qr/^ + (?: not \s )? bool $/ix }, + ], + }, "DBIx::Class::SQLAHacks"), _sql_maker_opts = +> {}, datetime_parser = +> undef, debugobj = +> bless({}, "DBIx::Class::Storage::Statistics"), savepoints = +> [], schema = +> 'fix', transaction_depth = +> 0, }, "DBIx::Class::Stora +ge::DBI::SQLite"), }, "MyApp::Schema::TestDatab +ase"), source_moniker => "Test", }, "DBIx::Class::ResultSourceHandl +e"), me => "Test", }, ], result_class => "MyApp::Model::TestDatabase::T +est", "select" => ["me.id", "me.subject", "me.messag +e", "me.date"], }, _result_class => "MyApp::Model::TestDatabase::Test", _source_handle => bless({ schema => 'fix', source_mo +niker => "Test" }, "DBIx::Class::ResultSourceHandle"), attrs => { alias => "me", result_class => "MyApp::Mo +del::TestDatabase::Test" }, cond => undef, count => undef, cursor => bless({ _dbh_gen => 0, args => [ 'fix', 'fix', undef, { alias => "me", as => 'fix', collapse => 'fix', from => 'fix', result_class => "MyApp::Model: +:TestDatabase::Test", "select" => 'fix', where => 'fix', }, ], attrs => 'fix', "pos" => 1, sth => bless({ # tied DBI::st }, "DBI::st"), storage => 'fix', }, "DBIx::Class::Storage::DBI::Cursor"), pager => undef, }, "DBIx::Class::ResultSet"), template => "list_messages.tt", }; $a->{messages}{_attrs}{from}[0]{"-source_handle"}{schema}{source_reg +istrations}{Test}{_unique_constraints}{primary} = $a->{messages}{_att +rs}{from}[0]{"-source_handle"}{schema}{source_registrations}{Test}{_p +rimaries}; $a->{messages}{_attrs}{from}[0]{"-source_handle"}{schema}{source_reg +istrations}{Test}{schema} = $a->{messages}{_attrs}{from}[0]{"-source_ +handle"}{schema}; $a->{messages}{_attrs}{from}[0]{"-source_handle"}{schema}{storage}{s +chema} = $a->{messages}{_attrs}{from}[0]{"-source_handle"}{schema}; $a->{messages}{_source_handle}{schema} = $a->{messages}{_attrs}{from +}[0]{"-source_handle"}{schema}; $a->{messages}{cursor}{args}[0] = $a->{messages}{_attrs}{from}; $a->{messages}{cursor}{args}[1] = $a->{messages}{_attrs}{"select"}; $a->{messages}{cursor}{args}[3]{as} = $a->{messages}{_attrs}{as}; $a->{messages}{cursor}{args}[3]{collapse} = $a->{messages}{_attrs}{c +ollapse}; $a->{messages}{cursor}{args}[3]{from} = $a->{messages}{_attrs}{from} +; $a->{messages}{cursor}{args}[3]{"select"} = $a->{messages}{_attrs}{" +select"}; $a->{messages}{cursor}{args}[3]{where} = $a->{messages}{cursor}{args +}[2]; $a->{messages}{cursor}{attrs} = $a->{messages}{cursor}{args}[3]; $a->{messages}{cursor}{storage} = $a->{messages}{_attrs}{from}[0]{"- +source_handle"}{schema}{storage}; $a; } Config do { my $a = { "Action::RenderView" => { ignore_classes => [ "DBIx::Class::ResultSource::Table", "DBIx::Class::ResultSourceHandle", "DateTime", ], scrubber_func => sub { "???" }, }, "Plugin::ConfigLoader" => {}, home => "C:\\MyApp", name => "MyApp", root => bless({ dirs => ["", "MyApp", "root"], file_spec_class => +undef, volume => "C:" }, "Path::Class::Dir"), static => { debug => 1, dirs => [], ignore_dirs => [], ignore_extensions => ["tmpl", "tt", "tt2", "html", "xhtml"], include_path => ['fix'], mime_types => {}, mime_types_obj => bless({}, "MIME::Types"), no_logs => 1, }, }; $a->{static}{include_path}[0] = $a->{root}; $a; } MyApp on Catalyst 5.8002

"Its not how hard you work, its how much you get done."

Replies are listed 'Best First'.
Re: Catalyst - Model Data Not Rendering in TT Template
by Khen1950fx (Canon) on Mar 16, 2010 at 06:40 UTC
    I've tested everything for syntax. The syntax is in order; however, there seems to be a problem with the DTD. The DTD isn't valid. This seems to be the main sticking point:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml1.dtd">
    Here's a validator to double-check.
      Thanks for checking things out Khen1950fx , and thanks for the link to the validator. The DTD is definitely not valid and needs to be fixed. I tried running the app with the statement commented out that stores 'messages' in the stash, and the web page renders and displays OK (minus the values from the database of course).

      #$c->stash->{messages} = $c->model('TestDatabase::test');

      There must be something about the structure of 'messages' in the stash that TT doesn't like. I don't know enough about DBIx::Class (yet) to know what to look for, but I'll keep digging. Thanks again.

      "Its not how hard you work, its how much you get done."

Re: Catalyst - Model Data Not Rendering in TT Template
by roho (Chancellor) on Mar 20, 2010 at 20:37 UTC
    To follow up, the problem was a missing Perl module: "DateTime::Format::SQLite". I discovered this by removing the "render_die => 1," line from 'lib\MyApp\View\TT.pm' so that instead of dumping the 200+ debug lines on the web page display, it displayed the missing module message. After installing the module, the page displayed perfectly.

    "Its not how hard you work, its how much you get done."

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://828813]
Approved by toolic
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (6)
As of 2020-02-21 13:11 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    What numbers are you going to focus on primarily in 2020?










    Results (95 votes). Check out past polls.

    Notices?