Question about the Dancer2 tutorial under Windows/Apache as an app...
Perl Dancer Community: I am converting from Dancer to Dancer2 (better late than never) and also developing some preliminary curriculum materials for CoderDojo using Perl Dancer2 as a framework for web development. I started with SawyerX's tutorial page: http://search.cpan.org/~xsawyerx/Dancer2/lib/Dancer2/Tutorial.pod The "dancr.pl" tutorial program ran just fine under the port 3000 server and the tutorial was useful and instructive: C:\Users\CoderDojo\Perl\Dancer\dancr>perl dancr.pl
Dancer2 v0.160001 server 2496 listening on http://0.0.0.0:3000
I ran into an issue when I tried to convert this demo into an app that would run under Apache in a Windows environment, however. The *crux* of the issue is that the "$flash message" does not work in the app (I suspect because the global variable $flash and the two subroutines are not part of a route, but I could *really* use an explanation, if this issue is obvious to someone: I created the app as normal: C:\Apache24\htdocs>*dancer2 -a dancr* + dancr + dancr\config.yml + dancr\cpanfile + dancr\Makefile.PL + dancr\MANIFEST.SKIP + dancr\bin + dancr\bin\app.psgi + dancr\environments + dancr\environments\development.yml + dancr\environments\production.yml + dancr\lib + dancr\lib\dancr.pm + dancr\public + dancr\public\dispatch.cgi + dancr\public\dispatch.fcgi + dancr\public\404.html + dancr\public\500.html + dancr\public\favicon.ico + dancr\public\css + dancr\public\css\error.css + dancr\public\css\style.css + dancr\public\images + dancr\public\images\perldancer-bg.jpg + dancr\public\images\perldancer.jpg + dancr\public\javascripts + dancr\public\javascripts\jquery.js + dancr\t + dancr\t\001_base.t + dancr\t\002_index_route.t + dancr\views + dancr\views\index.tt + dancr\views\layouts + dancr\views\layouts\main.tt With the resulting app files, I added the code from the original "dancr.pl" demo to the applications "dancr.pm" module: package dancr; use Dancer2; our $VERSION = '0.1'; get '/' => sub { template 'index'; }; true; I had to make the following adjustments to the code for Windows/Apache: (1) Change the session to YAML #set 'session' => 'Simple'; set 'session' => 'YAML'; (2) Adjust the path for request->base: # $tokens->{'css_url'} = request->base . 'css/dancr.css'; $tokens->{'css_url'} = request->base . '/css/dancr.css'; Everything with the app works as expected *except* for the "$flash message" code: my $flash; sub set_flash($message) { my $message = shift; $flash = $message; } sub get_flash { my $message = $flash; $flash = ''; return $message; } I suspect that since these subs are outside a route, perhaps I'm getting an effect about the scope of the variables... but calls to these subroutines do *not* set $flash or $message as expected: template 'show_entries.tt', { 'msg' => get_flash, set_flash('New entry posted!'); set_flash('You are logged in.'); set_flash('You are logged out.'); For each of these, the $flash variable (which is a free-standing global in the module) is never set... and so the get_flash sub never returns a value. -- Prairie Nyx prairienyx@gmail.com
Strange. Why do you have the ($message) in the prototype of the function? sub set_flash($message) { If I have that I get a warning: Illegal character in prototype for set_flash : $message at Anyway you can put debug("set_flash: $message") in the set_flash functions to see on the console if it is really executed. If that does not solve the problem, could you share a small but full example that does work? (At least the full .pm file) Gabor On Sun, May 31, 2015 at 6:47 AM, Prairie Nyx <prairienyx@gmail.com> wrote:
Perl Dancer Community:
I am converting from Dancer to Dancer2 (better late than never) and also developing some preliminary curriculum materials for CoderDojo using Perl Dancer2 as a framework for web development.
I started with SawyerX's tutorial page:
http://search.cpan.org/~xsawyerx/Dancer2/lib/Dancer2/Tutorial.pod
The "dancr.pl" tutorial program ran just fine under the port 3000 server and the tutorial was useful and instructive:
C:\Users\CoderDojo\Perl\Dancer\dancr>perl dancr.pl
Dancer2 v0.160001 server 2496 listening on http://0.0.0.0:3000
I ran into an issue when I tried to convert this demo into an app that would run under Apache in a Windows environment, however.
The *crux* of the issue is that the "$flash message" does not work in the app (I suspect because the global variable $flash and the two subroutines are not part of a route, but I could *really* use an explanation, if this issue is obvious to someone:
I created the app as normal:
C:\Apache24\htdocs>*dancer2 -a dancr* + dancr + dancr\config.yml + dancr\cpanfile + dancr\Makefile.PL + dancr\MANIFEST.SKIP + dancr\bin + dancr\bin\app.psgi + dancr\environments + dancr\environments\development.yml + dancr\environments\production.yml + dancr\lib + dancr\lib\dancr.pm + dancr\public + dancr\public\dispatch.cgi + dancr\public\dispatch.fcgi + dancr\public\404.html + dancr\public\500.html + dancr\public\favicon.ico + dancr\public\css + dancr\public\css\error.css + dancr\public\css\style.css + dancr\public\images + dancr\public\images\perldancer-bg.jpg + dancr\public\images\perldancer.jpg + dancr\public\javascripts + dancr\public\javascripts\jquery.js + dancr\t + dancr\t\001_base.t + dancr\t\002_index_route.t + dancr\views + dancr\views\index.tt + dancr\views\layouts + dancr\views\layouts\main.tt
With the resulting app files, I added the code from the original "dancr.pl" demo to the applications "dancr.pm" module:
package dancr; use Dancer2;
our $VERSION = '0.1';
get '/' => sub { template 'index'; };
true;
I had to make the following adjustments to the code for Windows/Apache:
(1) Change the session to YAML
#set 'session' => 'Simple'; set 'session' => 'YAML';
(2) Adjust the path for request->base:
# $tokens->{'css_url'} = request->base . 'css/dancr.css'; $tokens->{'css_url'} = request->base . '/css/dancr.css';
Everything with the app works as expected *except* for the "$flash message" code:
my $flash;
sub set_flash($message) { my $message = shift;
$flash = $message; }
sub get_flash { my $message = $flash; $flash = '';
return $message; }
I suspect that since these subs are outside a route, perhaps I'm getting an effect about the scope of the variables... but calls to these subroutines do *not* set $flash or $message as expected:
template 'show_entries.tt', { 'msg' => get_flash,
set_flash('New entry posted!');
set_flash('You are logged in.');
set_flash('You are logged out.');
For each of these, the $flash variable (which is a free-standing global in the module) is never set... and so the get_flash sub never returns a value.
-- Prairie Nyx prairienyx@gmail.com
_______________________________________________ dancer-users mailing list dancer-users@dancer.pm http://lists.preshweb.co.uk/mailman/listinfo/dancer-users
Here is the entire source for the "almost working" dancr.pl tutorial demo, implemented as an application under Windows/Apache: [*.../htdocs/dancr/lib/dancr.pm <http://dancr.pm>*] Note - Changes from " dancer.pl" in yellow... ----------------------------------------------------------------------------- package dancr; use strict; use warnings; use Dancer2; use DBI; use File::Spec; use File::Slurp; use Template; our $VERSION = '0.1'; # set 'database' => File::Spec->catfile(File::Spec->tmpdir(), 'dancr.db'); # Set the database to live under the application directory... set 'database' => 'C:\Apache24\htdocs\dancr\dancr.db'; #set 'session' => 'Simple'; set 'session' => 'YAML'; set 'template' => 'template_toolkit'; set 'logger' => 'console'; set 'log' => 'debug'; set 'show_errors' => 1; set 'startup_info' => 1; set 'warnings' => 1; set 'username' => 'admin'; set 'password' => 'password'; set 'layout' => 'main'; my $flash; sub set_flash { my $message = shift; $flash = $message; } sub get_flash { my $message = $flash; $flash = ''; return $message; } sub connect_db { my $dbh = DBI->connect("dbi:SQLite:dbname=".setting('database')) or die $DBI::errstr; return $dbh; } sub init_db { my $db = connect_db(); my $schema = read_file('./schema.sql'); $db->do($schema) or die $db->errstr; } hook before_template => sub { my $tokens = shift; # $tokens->{'css_url'} = request->base . 'css/dancr.css'; $tokens->{'css_url'} = request->base . '/css/dancr.css'; $tokens->{'login_url'} = uri_for('/login'); $tokens->{'logout_url'} = uri_for('/logout'); $flash=''; }; get '/' => sub { my $db = connect_db(); my $sql = 'select id, title, text from entries order by id desc'; my $sth = $db->prepare($sql) or die $db->errstr; $sth->execute or die $sth->errstr; template 'show_entries.tt', { 'msg' => get_flash, 'add_entry_url' => uri_for('/add'), 'entries' => $sth->fetchall_hashref('id'), }; }; post '/add' => sub { if ( not session('logged_in') ) { send_error("Not logged in", 401); } my $db = connect_db(); my $sql = 'insert into entries (title, text) values (?, ?)'; my $sth = $db->prepare($sql) or die $db->errstr; $sth->execute(params->{'title'}, params->{'text'}) or die $sth->errstr; set_flash('New entry posted!'); redirect '/'; }; any ['get', 'post'] => '/login' => sub { my $err; my $session = session; if ( request->method() eq "POST" ) { # process form input if ( params->{'username'} ne setting('username') ) { $err = "Invalid username"; } elsif ( params->{'password'} ne setting('password') ) { $err = "Invalid password"; } else { session 'logged_in' => true; set_flash('You are logged in.'); return redirect '/'; } } # display login form template 'login.tt', { 'err' => $err, }; }; get '/logout' => sub { app->destroy_session; set_flash('You are logged out.'); redirect '/'; }; init_db(); start; true; ----------------------------------------------------------------------------- [*http.conf*] <Directory "C:/Apache24/htdocs/dancr"> AllowOverride None Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch Order allow,deny Allow from all AddHandler cgi-script .cgi </Directory> ScriptAlias /dancr "C:/Apache24/htdocs/dancr/public/dispatch.cgi" It all seems to boil down to the "*my $flash;*" global variable that never gets set correctly in "sub set_flash" (or read in get_flash)... I think it must be something about variable scope since the global and the subs are not part of a route in the context of the app... --------------------------------- my $flash; sub set_flash { my $message = shift; $flash = $message; } --------------------------------- Thank you for any input about this... I'm sure it's something obvious that I'm missing... but I'm hoping I can be enlightened... Prairie Nyx On Sat, May 30, 2015 at 10:47 PM, Prairie Nyx <prairienyx@gmail.com> wrote:
Perl Dancer Community:
I am converting from Dancer to Dancer2 (better late than never) and also developing some preliminary curriculum materials for CoderDojo using Perl Dancer2 as a framework for web development.
I started with SawyerX's tutorial page:
http://search.cpan.org/~xsawyerx/Dancer2/lib/Dancer2/Tutorial.pod
The "dancr.pl" tutorial program ran just fine under the port 3000 server and the tutorial was useful and instructive:
C:\Users\CoderDojo\Perl\Dancer\dancr>perl dancr.pl
Dancer2 v0.160001 server 2496 listening on http://0.0.0.0:3000
I ran into an issue when I tried to convert this demo into an app that would run under Apache in a Windows environment, however.
The *crux* of the issue is that the "$flash message" does not work in the app (I suspect because the global variable $flash and the two subroutines are not part of a route, but I could *really* use an explanation, if this issue is obvious to someone:
I created the app as normal:
C:\Apache24\htdocs>*dancer2 -a dancr* + dancr + dancr\config.yml + dancr\cpanfile + dancr\Makefile.PL + dancr\MANIFEST.SKIP + dancr\bin + dancr\bin\app.psgi + dancr\environments + dancr\environments\development.yml + dancr\environments\production.yml + dancr\lib + dancr\lib\dancr.pm + dancr\public + dancr\public\dispatch.cgi + dancr\public\dispatch.fcgi + dancr\public\404.html + dancr\public\500.html + dancr\public\favicon.ico + dancr\public\css + dancr\public\css\error.css + dancr\public\css\style.css + dancr\public\images + dancr\public\images\perldancer-bg.jpg + dancr\public\images\perldancer.jpg + dancr\public\javascripts + dancr\public\javascripts\jquery.js + dancr\t + dancr\t\001_base.t + dancr\t\002_index_route.t + dancr\views + dancr\views\index.tt + dancr\views\layouts + dancr\views\layouts\main.tt
With the resulting app files, I added the code from the original "dancr.pl" demo to the applications "dancr.pm" module:
package dancr; use Dancer2;
our $VERSION = '0.1';
get '/' => sub { template 'index'; };
true;
I had to make the following adjustments to the code for Windows/Apache:
(1) Change the session to YAML
#set 'session' => 'Simple'; set 'session' => 'YAML';
(2) Adjust the path for request->base:
# $tokens->{'css_url'} = request->base . 'css/dancr.css'; $tokens->{'css_url'} = request->base . '/css/dancr.css';
Everything with the app works as expected *except* for the "$flash message" code:
my $flash;
sub set_flash($message) { my $message = shift;
$flash = $message; }
sub get_flash { my $message = $flash; $flash = '';
return $message; }
I suspect that since these subs are outside a route, perhaps I'm getting an effect about the scope of the variables... but calls to these subroutines do *not* set $flash or $message as expected:
template 'show_entries.tt', { 'msg' => get_flash,
set_flash('New entry posted!');
set_flash('You are logged in.');
set_flash('You are logged out.');
For each of these, the $flash variable (which is a free-standing global in the module) is never set... and so the get_flash sub never returns a value.
-- Prairie Nyx prairienyx@gmail.com
-- Prairie Nyx prairienyx@gmail.com
I'd suggest you run the stand-alone bin/app.pl or plackup bin/app.psgi without Apache till you have this figured out then. That way you can be sure the problem is not due to the use of Apache. Have you tried adding debug() calls to the set_flash and get_flash functions to see if they are executed when you access the URLs? Gabor
Well... looks like I'm going to answer my own question after thinking about how as a CGI app, the vars are completely fresh with each call... so I'll play with setting a "session variable" and then not look back at this example... :-) Thank you anyway! Prairie Nyx On Sat, May 30, 2015 at 11:10 PM, Prairie Nyx <prairienyx@gmail.com> wrote:
Here is the entire source for the "almost working" dancr.pl tutorial demo, implemented as an application under Windows/Apache:
[*.../htdocs/dancr/lib/dancr.pm <http://dancr.pm>*] Note - Changes from "dancer.pl" in yellow...
-----------------------------------------------------------------------------
package dancr;
use strict; use warnings;
use Dancer2; use DBI; use File::Spec; use File::Slurp; use Template;
our $VERSION = '0.1';
# set 'database' => File::Spec->catfile(File::Spec->tmpdir(), 'dancr.db'); # Set the database to live under the application directory... set 'database' => 'C:\Apache24\htdocs\dancr\dancr.db'; #set 'session' => 'Simple'; set 'session' => 'YAML'; set 'template' => 'template_toolkit'; set 'logger' => 'console'; set 'log' => 'debug'; set 'show_errors' => 1; set 'startup_info' => 1; set 'warnings' => 1; set 'username' => 'admin'; set 'password' => 'password'; set 'layout' => 'main';
my $flash;
sub set_flash { my $message = shift;
$flash = $message; }
sub get_flash { my $message = $flash; $flash = '';
return $message; }
sub connect_db { my $dbh = DBI->connect("dbi:SQLite:dbname=".setting('database')) or die $DBI::errstr;
return $dbh; }
sub init_db { my $db = connect_db(); my $schema = read_file('./schema.sql'); $db->do($schema) or die $db->errstr; }
hook before_template => sub { my $tokens = shift;
# $tokens->{'css_url'} = request->base . 'css/dancr.css'; $tokens->{'css_url'} = request->base . '/css/dancr.css'; $tokens->{'login_url'} = uri_for('/login'); $tokens->{'logout_url'} = uri_for('/logout'); $flash=''; };
get '/' => sub { my $db = connect_db(); my $sql = 'select id, title, text from entries order by id desc'; my $sth = $db->prepare($sql) or die $db->errstr; $sth->execute or die $sth->errstr;
template 'show_entries.tt', { 'msg' => get_flash, 'add_entry_url' => uri_for('/add'), 'entries' => $sth->fetchall_hashref('id'), };
};
post '/add' => sub { if ( not session('logged_in') ) { send_error("Not logged in", 401); }
my $db = connect_db(); my $sql = 'insert into entries (title, text) values (?, ?)'; my $sth = $db->prepare($sql) or die $db->errstr; $sth->execute(params->{'title'}, params->{'text'}) or die $sth->errstr;
set_flash('New entry posted!'); redirect '/'; };
any ['get', 'post'] => '/login' => sub { my $err; my $session = session;
if ( request->method() eq "POST" ) { # process form input if ( params->{'username'} ne setting('username') ) { $err = "Invalid username"; } elsif ( params->{'password'} ne setting('password') ) { $err = "Invalid password"; } else { session 'logged_in' => true; set_flash('You are logged in.'); return redirect '/'; } }
# display login form template 'login.tt', { 'err' => $err, };
};
get '/logout' => sub { app->destroy_session; set_flash('You are logged out.'); redirect '/'; };
init_db(); start;
true;
-----------------------------------------------------------------------------
[*http.conf*]
<Directory "C:/Apache24/htdocs/dancr"> AllowOverride None Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch Order allow,deny Allow from all AddHandler cgi-script .cgi </Directory>
ScriptAlias /dancr "C:/Apache24/htdocs/dancr/public/dispatch.cgi"
It all seems to boil down to the "*my $flash;*" global variable that never gets set correctly in "sub set_flash" (or read in get_flash)... I think it must be something about variable scope since the global and the subs are not part of a route in the context of the app...
--------------------------------- my $flash;
sub set_flash { my $message = shift;
$flash = $message; } ---------------------------------
Thank you for any input about this... I'm sure it's something obvious that I'm missing... but I'm hoping I can be enlightened...
Prairie Nyx
On Sat, May 30, 2015 at 10:47 PM, Prairie Nyx <prairienyx@gmail.com> wrote:
Perl Dancer Community:
I am converting from Dancer to Dancer2 (better late than never) and also developing some preliminary curriculum materials for CoderDojo using Perl Dancer2 as a framework for web development.
I started with SawyerX's tutorial page:
http://search.cpan.org/~xsawyerx/Dancer2/lib/Dancer2/Tutorial.pod
The "dancr.pl" tutorial program ran just fine under the port 3000 server and the tutorial was useful and instructive:
C:\Users\CoderDojo\Perl\Dancer\dancr>perl dancr.pl
Dancer2 v0.160001 server 2496 listening on http://0.0.0.0:3000
I ran into an issue when I tried to convert this demo into an app that would run under Apache in a Windows environment, however.
The *crux* of the issue is that the "$flash message" does not work in the app (I suspect because the global variable $flash and the two subroutines are not part of a route, but I could *really* use an explanation, if this issue is obvious to someone:
I created the app as normal:
C:\Apache24\htdocs>*dancer2 -a dancr* + dancr + dancr\config.yml + dancr\cpanfile + dancr\Makefile.PL + dancr\MANIFEST.SKIP + dancr\bin + dancr\bin\app.psgi + dancr\environments + dancr\environments\development.yml + dancr\environments\production.yml + dancr\lib + dancr\lib\dancr.pm + dancr\public + dancr\public\dispatch.cgi + dancr\public\dispatch.fcgi + dancr\public\404.html + dancr\public\500.html + dancr\public\favicon.ico + dancr\public\css + dancr\public\css\error.css + dancr\public\css\style.css + dancr\public\images + dancr\public\images\perldancer-bg.jpg + dancr\public\images\perldancer.jpg + dancr\public\javascripts + dancr\public\javascripts\jquery.js + dancr\t + dancr\t\001_base.t + dancr\t\002_index_route.t + dancr\views + dancr\views\index.tt + dancr\views\layouts + dancr\views\layouts\main.tt
With the resulting app files, I added the code from the original " dancr.pl" demo to the applications "dancr.pm" module:
package dancr; use Dancer2;
our $VERSION = '0.1';
get '/' => sub { template 'index'; };
true;
I had to make the following adjustments to the code for Windows/Apache:
(1) Change the session to YAML
#set 'session' => 'Simple'; set 'session' => 'YAML';
(2) Adjust the path for request->base:
# $tokens->{'css_url'} = request->base . 'css/dancr.css'; $tokens->{'css_url'} = request->base . '/css/dancr.css';
Everything with the app works as expected *except* for the "$flash message" code:
my $flash;
sub set_flash($message) { my $message = shift;
$flash = $message; }
sub get_flash { my $message = $flash; $flash = '';
return $message; }
I suspect that since these subs are outside a route, perhaps I'm getting an effect about the scope of the variables... but calls to these subroutines do *not* set $flash or $message as expected:
template 'show_entries.tt', { 'msg' => get_flash,
set_flash('New entry posted!');
set_flash('You are logged in.');
set_flash('You are logged out.');
For each of these, the $flash variable (which is a free-standing global in the module) is never set... and so the get_flash sub never returns a value.
-- Prairie Nyx prairienyx@gmail.com
-- Prairie Nyx prairienyx@gmail.com
-- Prairie Nyx prairienyx@gmail.com
participants (2)
-
Gabor Szabo -
Prairie Nyx