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

Hi all,

a while ago i wrote Mojolicious::Lite: Should i use the build-in web server?.

In the last months I didn't have the time to dive a bit deeper into this stuff.

But anyway, one must start somehow, regardless how poor the first approach might be.

Here is what did:

Nose.pm

package Nose; use XML::LibXML; use Moo::Role; my $xml = sub { my ( $self, $params ) = @_; # you really need $self my $doc = XML::LibXML::Document->new( '1.0', 'utf-8' ); my $root = $doc->createElement("myapp"); my $tag = $doc->createElement("nose"); my $value = $params->{"nose"}; $tag->appendTextNode($value); $root->appendChild($tag); $doc->setDocumentElement($root); $doc->toString(); }; sub nose { my ( $self, $params ) = @_; $self->$xml($params); } 1; __END__

Karl.pm

package Karl; use Moo; with qw(Nose); 1; __END__

myapp.psgi

#!/usr/bin/env perl use Mojolicious::Lite; use Karl; my $moo = Karl->new(); get '/foo' => sub { my $c = shift; my $params->{nose} = $c->param('nose'); $c->render( text => $moo->nose($params) ); }; app->start; __END__

run.pl

#!/usr/bin/env perl use strict; use warnings; use Mojo::Server::Hypnotoad; my $app = q(/Users/karl/Documents/workspace/monks/MyMoo/MyMojo/myapp.p +sgi); my $hypnotoad = Mojo::Server::Hypnotoad->new; $hypnotoad->run($app) __END__

For what this stuff is (or should be) good for please see ibidem. I didn't want to quote it because it is a bit extensive. Sorry for the inconvenience.

Basically it does why i want. I tried to simplify it as much i could (skipping the database part a.s.o.).

But this approach seems to be so simple that i'm in doubt if i miss something.

Thank you very much for any hint.

Update: The database part that i skipped for simplification:

Connector.pm

package Connector; use DBIx::Connector; use Types::Standard qw(InstanceOf); use Moo::Role; has 'connector' => ( is => 'ro', builder => '_build_connector', handles => [qw(dbh txn)], isa => InstanceOf( ['DBIx::Connector'] ), ); sub _build_connector { my $dsn = qq(dbi:SQLite:dbname=db/myDB.sqlite); my $conn = DBIx::Connector->new( $dsn, { RaiseError => 1, AutoCommit => 1, } ); $conn->mode('fixup'); $conn; } 1; __END__

MyApp.pm

package MyApp; use Moo; with qw(Connector); 1; __END__

myapp.pl

use Mojolicious::Lite; use MyApp; my $moo = MyApp->new(); get '/foo' => sub { my $c = shift; my $query = qq(select nose from myTable); my $dbh = $moo->dbh; my $sth = $moo->txn( sub { my $sth = $dbh->prepare($query); $sth->execute; $sth; } ); my $row = $sth->fetch; $c->render( text => "<h1>$row->[0]</h1>" ); }; get '/bar' => sub { my $c = shift; my $query = qq(select monk from myTable); my $dbh = $moo->dbh; my $sth = $moo->txn( sub { my $sth = $dbh->prepare($query); $sth->execute; $sth; } ); my $row = $sth->fetch; $c->render( text => "<h1>$row->[0]</h1>" ); }; app->start; __END__

I wasn't aware of this prefork issue but it seems like my example works as designed with hypnotoad ;-)

Edit: Added comment about $self.

Best regards, Karl

«The Crux of the Biscuit is the Apostrophe»

Replies are listed 'Best First'.
Re: RFC: Mojolicious::Lite and Moo: A Very Basic Application Layout
by jeffa (Bishop) on Aug 05, 2015 at 21:19 UTC

    This is even more simple:

    use strict; use warnings; use Mojolicious::Lite; get '/' => sub { my $c = shift; $c->stash( nose => $c->param( 'nose' ) || 'karl' ); $c->render( template => 'nose', format => 'xml' ); }; app->start; __DATA__ @@ nose.xml.ep <?xml version="1.0" encoding="UTF-8"?> <myapp> <nose><%= $nose %></nose> </myapp>

    I can understand wanting to retain the method you use to create the XML document itself (better validation), but do you really need those objects?

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    

      Thanks jeffa for the cool hint.

      "...do you really need those objects?"

      Who knows ;-)

      But what i really need is something like:

      <myapp> <nose> <row><foo>this</foo><bar>that</bar></row> <row><foo>nose</foo><bar>cuke</bar></row> <!-- and so on --> </nose> </myapp>

      As i wrote: I tried to simplify it as much... :-)

      Update: And i considered to have one role for each route (about 50). Good idea? i don't know yet.

      Best regards, Karl

      «The Crux of the Biscuit is the Apostrophe»

Re: RFC: Mojolicious::Lite and Moo: A Very Basic Application Layout
by Anonymous Monk on Aug 05, 2015 at 21:11 UTC
    Whats with the anonysub and fake global/closure? Also you got a syntax error
      "...fake global/closure? Also you got a syntax error..."

      What do you mean with fake global closure?

      I guess $xml is a lexical method, isn't it?

      And my code compiles/runs: http://localhost:8080/foo?nose=anonmonk yields:

      <?xml version="1.0" encoding="utf-8"?> <myapp><nose>anonmonk</nose></myapp>

      Regards, Karl

      «The Crux of the Biscuit is the Apostrophe»

        This looks like error  my $params->{nose} = $c->param('nose');

        B::Deparse 1.1401 (perl 5.16...) doesn't know what that is :) ($my $params{'nose'} = $c->param('nose'));

        I guess $xml is a lexical method, isn't it?

        gratuitous :)

        tobyinkster's argument goes

        Stop writing 'private' methods
        ●If a method is useful for end-users, then promote it to a public method.
        ●If a method exists in your namespace, then document it.
        ●Otherwise, use 'lexical methods' – coderefs.
        

        My argument goes, if you want it as a seperate method, document it, use _private convention, its as old as perl and its open

        otherwise put it in sub nose

        8/10 times I see a _lexical_method its useful to subclasses

        The same goes for  my %classdataUsefulButInaccessibleDirectly 8/10 times it should be  our %...

        Its like insideout objects ... as soon as you need to subclass and do something the author didn't think , all these OOPy protections become hurdles