Cookie Notice

As far as I know, and as far as I remember, nothing in this page does anything with Cookies.

2012/01/18

I Can't Help Feeling Stupid Standing 'Round

We're jumping from straight Perl and CGI.pm for web applications to an MVC, a jump we've been wanting to do for years. I've tried Catalyst a couple times, and both times, I spend most of my learning curve thinking "If I wrote this up without an MVC, I'd be done and on to the next thing by now", and in general, I get told much the same thing by my bosses, in the form of "move on  to this other, non-MVC-related task".

But that was Catalyst, which seemingly brings along half of CPAN with it. This time, I'm trying Dancer with Template Toolkit, and I'm getting some progress. Here's a chunk of code I have working.

package TestApp ;
use Dancer ':syntax' ;
use lib '/home/jacoby/lib' ;
use MyDB 'db_connect' ;
use DateTime ;

our $VERSION = '0.1' ;

get '/' => sub {
    template 'index' ;
    } ;

get '/weather' => sub {
    my $dbh = db_connect() ;
    my $sql = <<SQL;
    # Last Eight Hours
    SELECT  time , AVG( temp_f )
    FROM weather WHERE zip = "47909"
    AND HOUR( TIMEDIFF( SYSDATE() , time ) ) < 9
    GROUP BY HOUR(time)
    ORDER BY time
SQL
    my $hr = $dbh->selectall_arrayref( $sql ) or croak $dbh->errstr ;
    my @hr ;
    for my $point ( @$hr ) {
        my ( $time, $temp ) = @$point ;
        my @time = split /\D+/ ,  $time ;
        my $dt = DateTime->new(
            year  => $time[0] ,
            month => $time[1] ,
            day   => $time[2] ,
            hour => $time[3] ,
            minute => $time[4] ,
            second => $time[5] ,
            ) ;
        my $data ;
        $data->{ time } = $dt->format_cldr( 'h:mm a' ) ;
        $data->{ temp } = sprintf '%.1f', $temp ;
        next if $data->{ time } !~ /00/ ;
        push @hr, $data ;
        }
    my $vars = {
        string => 'Temperature in West Lafayette for the last 8 hours' ,
        weather => \@hr ,
        } ;

    template 'weather' , { var => $vars } ;
    } ;

true ;

A few notes here: MyDB.pm is a module I use to get a DBI object without putting the DB connection info into the code, making it safer for me to dump it in public like this. I've been collecting weather data for the West Lafayette area so I have a significant set to use when I want to play around with SQL and R.

Normally, when I pass things around, I pass, for example, a hash of hashes, then sort on the keys of the hash. Here, I'm making an array of hashes, so it's pre-sorted. I'm liking that. Still wrapping my head around how to put data where Template Toolkit can get to it. I like having my HTML as HTML, with occasional <code>[% FOREACH object IN array %] [% object.value %] [% END %] </code> sorts of thing added. I used to have lots of <code> print qq{<div> $div_contents </div>} ;</code> in my code, before I got here, where the coding standard is <code> print $cgi->div( $div_contents ) ; </code>, which is fine and all, but I always was very proud of my HTML and it feels good to be getting back into writing it in the midst of the coming of HTML5 and all.

But I'm curious if I did this the correct way of putting together the data, or if there's an easier better way that isn't apparent from the Dancer::Cookbook POD. It seems like I should be expecting a greater leap than this seems to give. What am I missing, if anything?

7 comments:

  1. This is your controller file and it has model code in it. (the sql, result iteration, and date time parsing)

    Perhaps what you're missing is that you're not using MVC separation?

    ReplyDelete
  2. This is your controller file and it has model code in it. (the sql, result iteration, and date time parsing)

    Perhaps what you're missing is that you're not using MVC separation?

    ReplyDelete
  3. This is your controller file and it has model code in it. (the sql, result iteration, and date time parsing)

    Perhaps what you're missing is that you're not using MVC separation?

    ReplyDelete
  4. @DavidIAm, that could be it, but I'm not seeing good sample code to show what I should be doing. Can you point me to some?

    ReplyDelete
  5. Use the cpan, Luke:

    http://search.cpan.org/~xsawyerx/Dancer-1.3091/lib/Dancer/Tutorial.pod

    Admittedly a simple example but it walks through a route handler that connects to a db and spits out some content via a template.

    ReplyDelete
  6. It's not so important how you separate, just that you do.

    Whether it's an ORM or your own module, just take all the database-related stuff and put it into a separate package:

    my @hr = MyCoolDBModel->new->list_of_hr_stuff(zip => 47909);

    ReplyDelete