1 package Catalyst::Helper;
4 use base 'Class::Accessor::Fast';
12 use Catalyst::Exception;
18 Catalyst::Helper - Bootstrap a Catalyst application
22 See L<Catalyst::Manual::Intro>
26 Bootstrap a Catalyst application. Autogenerates scripts
37 my ( $self, $class, $file ) = @_;
38 unless ( $cache{$class} ) {
40 $cache{$class} = eval "package $class; <DATA>";
42 my $data = $cache{$class};
43 my @files = split /^__(.+)__\n/m, $data;
46 my ( $name, $content ) = splice @files, 0, 2;
47 return $content if $name eq $file;
54 Create the main application skeleton.
59 my ( $self, $name ) = @_;
60 return 0 if $name =~ /[^\w\:]/;
61 $self->{name} = $name;
63 $self->{dir} =~ s/\:\:/-/g;
64 $self->{appprefix} = lc $self->{dir};
65 $self->{appprefix} =~ s/-/_/g;
66 $self->{startperl} = $Config{startperl};
67 $self->{scriptgen} = $Catalyst::CATALYST_SCRIPT_GEN;
68 $self->{author} = $self->{author} = $ENV{'AUTHOR'}
69 || eval { @{ [ getpwuid($<) ] }[6] }
70 || 'Catalyst developer';
88 This method is called by create.pl to make new components
97 $self->{author} = $self->{author} = $ENV{'AUTHOR'}
98 || eval { @{ [ getpwuid($<) ] }[6] }
100 $self->{base} = File::Spec->catdir( $FindBin::Bin, '..' );
101 unless ( $_[0] =~ /^(?:model|m|view|v|controller|c)$/i ) {
104 my $class = "Catalyst::Helper::$helper";
105 eval "require $class";
108 Catalyst::Exception->throw(
109 message => qq/Couldn't load helper "$class", "$@"/
113 if ( $class->can('mk_stuff') ) {
114 return 1 unless $class->mk_stuff( $self, @args );
119 my $name = shift || "Missing name for model/view/controller";
122 return 0 if $name =~ /[^\w\:]/;
123 $type = 'M' if $type =~ /model|m/i;
124 $type = 'V' if $type =~ /view|v/i;
125 $type = 'C' if $type =~ /controller|c/i;
126 $self->{type} = $type;
127 $self->{name} = $name;
128 $self->{class} = "$app\::$type\::$name";
131 my $appdir = File::Spec->catdir( split /\:\:/, $app );
133 File::Spec->catdir( $FindBin::Bin, '..', 'lib', $appdir, $type );
135 if ( $name =~ /\:/ ) {
136 my @path = split /\:\:/, $name;
138 $path = File::Spec->catdir( $path, @path );
141 $file = File::Spec->catfile( $path, "$file.pm" );
142 $self->{file} = $file;
145 $self->{test_dir} = File::Spec->catdir( $FindBin::Bin, '..', 't' );
146 $self->{test} = $self->next_test;
151 $comp = 'View' if $type eq 'V';
152 $comp = 'Controller' if $type eq 'C';
153 my $class = "Catalyst::Helper::$comp\::$helper";
154 eval "require $class";
157 Catalyst::Exception->throw(
158 message => qq/Couldn't load helper "$class", "$@"/
162 if ( $class->can('mk_compclass') ) {
163 return 1 unless $class->mk_compclass( $self, @args );
165 else { return 1 unless $self->_mk_compclass }
167 if ( $class->can('mk_comptest') ) {
168 $class->mk_comptest( $self, @args );
170 else { $self->_mk_comptest }
175 return 1 unless $self->_mk_compclass;
184 Surprisingly, this function makes a directory.
189 my ( $self, $dir ) = @_;
191 print qq/ exists "$dir"\n/;
195 print qq/created "$dir"\n/;
199 Catalyst::Exception->throw(
200 message => qq/Couldn't create "$dir", "$!"/
206 writes content to a file.
211 my ( $self, $file, $content ) = @_;
213 print qq/ exists "$file"\n/;
216 if ( my $f = IO::File->new("> $file") ) {
218 print qq/created "$file"\n/;
222 Catalyst::Exception->throw(
223 message => qq/Couldn't create "$file", "$!"/
232 my ( $self, $tname ) = @_;
233 if ($tname) { $tname = "$tname.t" }
235 my $name = $self->{name};
239 $tname = $prefix . '.t';
240 $self->{prefix} = $prefix;
241 $prefix = lc $prefix;
243 $self->{uri} = $prefix;
245 my $dir = $self->{test_dir};
246 my $type = $self->{type};
247 return File::Spec->catfile( $dir, $type, $tname );
252 Render and create a file from a template in DATA using
258 my ( $self, $file, $path, $vars ) = @_;
260 my $t = Template->new;
261 my $template = $self->get_file( ( caller(0) )[0], $file );
262 return 0 unless $template;
264 $t->process( \$template, { %{$self}, %$vars }, \$output );
265 $self->mk_file( $path, $output );
270 $self->mk_dir( $self->{dir} );
271 $self->{script} = File::Spec->catdir( $self->{dir}, 'script' );
272 $self->mk_dir( $self->{script} );
273 $self->{lib} = File::Spec->catdir( $self->{dir}, 'lib' );
274 $self->mk_dir( $self->{lib} );
275 $self->{root} = File::Spec->catdir( $self->{dir}, 'root' );
276 $self->mk_dir( $self->{root} );
277 $self->{t} = File::Spec->catdir( $self->{dir}, 't' );
278 $self->mk_dir( $self->{t} );
279 $self->mk_dir( File::Spec->catdir( $self->{t}, 'M' ) );
280 $self->mk_dir( File::Spec->catdir( $self->{t}, 'V' ) );
281 $self->mk_dir( File::Spec->catdir( $self->{t}, 'C' ) );
282 $self->{class} = File::Spec->catdir( split( /\:\:/, $self->{name} ) );
283 $self->{mod} = File::Spec->catdir( $self->{lib}, $self->{class} );
284 $self->mk_dir( $self->{mod} );
285 $self->{m} = File::Spec->catdir( $self->{mod}, 'M' );
286 $self->mk_dir( $self->{m} );
287 $self->{v} = File::Spec->catdir( $self->{mod}, 'V' );
288 $self->mk_dir( $self->{v} );
289 $self->{c} = File::Spec->catdir( $self->{mod}, 'C' );
290 $self->mk_dir( $self->{c} );
291 $self->{base} = File::Spec->rel2abs( $self->{dir} );
296 my $mod = $self->{mod};
297 $self->render_file( 'appclass', "$mod.pm" );
302 my $dir = $self->{dir};
303 $self->render_file( 'build', "$dir\/Build.PL" );
308 my $dir = $self->{dir};
309 $self->render_file( 'makefile', "$dir\/Makefile.PL" );
314 my $dir = $self->{dir};
315 $self->render_file( 'readme', "$dir\/README" );
320 my $dir = $self->{dir};
321 my $time = localtime time;
322 $self->render_file( 'changes', "$dir\/Changes", { time => $time } );
328 $self->render_file( 'apptest', "$t\/01app.t" );
329 $self->render_file( 'podtest', "$t\/02pod.t" );
330 $self->render_file( 'podcoveragetest', "$t\/03podcoverage.t" );
335 my $script = $self->{script};
336 my $appprefix = $self->{appprefix};
337 $self->render_file( 'cgi', "$script\/$appprefix\_cgi.pl" );
338 chmod 0700, "$script/$appprefix\_cgi.pl";
343 my $script = $self->{script};
344 my $appprefix = $self->{appprefix};
345 $self->render_file( 'fastcgi', "$script\/$appprefix\_fastcgi.pl" );
346 chmod 0700, "$script/$appprefix\_fastcgi.pl";
351 my $script = $self->{script};
352 my $appprefix = $self->{appprefix};
353 $self->render_file( 'server', "$script\/$appprefix\_server.pl" );
354 chmod 0700, "$script/$appprefix\_server.pl";
359 my $script = $self->{script};
360 my $appprefix = $self->{appprefix};
361 $self->render_file( 'test', "$script/$appprefix\_test.pl" );
362 chmod 0700, "$script/$appprefix\_test.pl";
367 my $script = $self->{script};
368 my $appprefix = $self->{appprefix};
369 $self->render_file( 'create', "$script\/$appprefix\_create.pl" );
370 chmod 0700, "$script/$appprefix\_create.pl";
375 my $file = $self->{file};
376 return $self->render_file( 'compclass', "$file" );
381 my $test = $self->{test};
382 $self->render_file( 'comptest', "$test" );
387 Helpers are classes that provide two methods.
389 * mk_compclass - creates the Component class
390 * mk_comptest - creates the Component test
392 So when you call C<bin/create view MyView TT>, create would try to execute
393 Catalyst::Helper::View::TT->mk_compclass and
394 Catalyst::Helper::View::TT->mk_comptest.
396 See L<Catalyst::Helper::View::TT> and L<Catalyst::Helper::Model::CDBI> for
399 All helper classes should be under one of the following namespaces.
401 Catalyst::Helper::Model::
402 Catalyst::Helper::View::
403 Catalyst::Helper::Controller::
407 The helpers will read author name from /etc/passwd by default.
408 To override, please export the AUTHOR variable.
412 L<Catalyst::Manual>, L<Catalyst::Test>, L<Catalyst::Request>,
413 L<Catalyst::Response>, L<Catalyst>
417 Sebastian Riedel, C<sri@oook.de>
421 This library is free software . You can redistribute it and/or modify
422 it under the same terms as perl itself.
433 use Catalyst qw/-Debug/;
435 our $VERSION = '0.01';
437 [% name %]->config( name => '[% name %]' );
443 [% name %] - Catalyst based application
447 script/[% appprefix %]_server.pl
451 Catalyst based application.
461 sub default : Private {
462 my ( $self, $c ) = @_;
463 $c->res->output('Congratulations, [% name %] is on Catalyst!');
474 This library is free software . You can redistribute it and/or modify
475 it under the same terms as perl itself.
481 unless ( eval "use Module::Build::Compat 0.02; 1" ) {
482 print "This module requires Module::Build to install itself.\n";
484 require ExtUtils::MakeMaker;
486 ExtUtils::MakeMaker::prompt( ' Install Module::Build now from CPAN?', 'y' );
488 unless ( $yn =~ /^y/i ) {
489 die " *** Cannot install without Module::Build. Exiting ...\n";
496 # Save this 'cause CPAN will chdir all over the place.
497 my $cwd = Cwd::cwd();
498 my $makefile = File::Spec->rel2abs($0);
500 CPAN::Shell->install('Module::Build::Compat')
501 or die " *** Cannot install without Module::Build. Exiting ...\n";
503 chdir $cwd or die "Cannot chdir() back to $cwd: $!";
505 eval "use Module::Build::Compat 0.02; 1" or die $@;
506 use lib '_build/lib';
507 Module::Build::Compat->run_build_pl( args => \@ARGV );
508 require Module::Build;
509 Module::Build::Compat->write_makefile( build_class => 'Module::Build' );
514 my $build = Catalyst::Build->new(
515 create_makefile_pl => 'passthrough',
517 module_name => '[% name %]',
518 requires => { Catalyst => '5.10' },
519 create_makefile_pl => 'passthrough',
520 script_files => [ glob('script/*') ],
521 test_files => [ glob('t/*.t'), glob('t/*/*.t') ]
523 $build->create_build_script;
525 Run script/[% appprefix %]_server.pl to test the application.
527 This file documents the revision history for Perl extension [% name %].
529 - initial revision, generated by Catalyst
531 use Test::More tests => 2;
532 use_ok( Catalyst::Test, '[% name %]' );
534 ok( request('/')->is_success );
538 eval "use Test::Pod 1.14";
539 plan skip_all => 'Test::Pod 1.14 required' if $@;
540 plan skip_all => 'set TEST_POD to enable this test' unless $ENV{TEST_POD};
546 eval "use Test::Pod::Coverage 1.04";
547 plan skip_all => 'Test::Pod::Coverage 1.04 required' if $@;
548 plan skip_all => 'set TEST_POD to enable this test' unless $ENV{TEST_POD};
550 all_pod_coverage_ok();
554 BEGIN { $ENV{CATALYST_ENGINE} ||= 'CGI' }
558 use lib "$FindBin::Bin/../lib";
567 [% appprefix %]_cgi.pl - Catalyst CGI
571 See L<Catalyst::Manual>
575 Run a Catalyst application as cgi.
579 Sebastian Riedel, C<sri@oook.de>
583 Copyright 2004 Sebastian Riedel. All rights reserved.
585 This library is free software. You can redistribute it and/or modify
586 it under the same terms as perl itself.
592 BEGIN { $ENV{CATALYST_ENGINE} ||= 'FastCGI' }
596 use lib "$FindBin::Bin/../lib";
605 [% appprefix %]_fastcgi.pl - Catalyst FastCGI
609 See L<Catalyst::Manual>
613 Run a Catalyst application as fastcgi.
617 Sebastian Riedel, C<sri@oook.de>
621 Copyright 2004 Sebastian Riedel. All rights reserved.
623 This library is free software. You can redistribute it and/or modify
624 it under the same terms as perl itself.
631 $ENV{CATALYST_ENGINE} ||= 'HTTP';
632 $ENV{CATALYST_SCRIPT_GEN} = [% scriptgen %];
639 use lib "$FindBin::Bin/../lib";
645 GetOptions( 'help|?' => \$help, 'port=s' => \$port );
647 pod2usage(1) if $help;
649 [% name %]->run($port);
655 [% appprefix %]_server.pl - Catalyst Testserver
659 [% appprefix %]_server.pl [options]
662 -? -help display this help and exits
663 -p -port port (defaults to 3000)
666 perldoc Catalyst::Manual
667 perldoc Catalyst::Manual::Intro
671 Run a Catalyst Testserver for this application.
675 Sebastian Riedel, C<sri@oook.de>
679 Copyright 2004 Sebastian Riedel. All rights reserved.
681 This library is free software. You can redistribute it and/or modify
682 it under the same terms as perl itself.
688 BEGIN { $ENV{CATALYST_ENGINE} ||= 'Test' }
694 use lib "$FindBin::Bin/../lib";
699 GetOptions( 'help|?' => \$help );
701 pod2usage(1) if ( $help || !$ARGV[0] );
703 print [% name %]->run($ARGV[0])->content . "\n";
709 [% appprefix %]_test.pl - Catalyst Test
713 [% appprefix %]_test.pl [options] uri
716 -help display this help and exits
719 [% appprefix %]_test.pl http://localhost/some_action
720 [% appprefix %]_test.pl /some_action
723 perldoc Catalyst::Manual
724 perldoc Catalyst::Manual::Intro
728 Run a Catalyst action from the comand line.
732 Sebastian Riedel, C<sri@oook.de>
736 Copyright 2004 Sebastian Riedel. All rights reserved.
738 This library is free software. You can redistribute it and/or modify
739 it under the same terms as perl itself.
748 use Catalyst::Helper;
752 GetOptions( 'help|?' => \$help );
754 pod2usage(1) if ( $help || !$ARGV[0] );
756 my $helper = Catalyst::Helper->new;
757 pod2usage(1) unless $helper->mk_component( '[% name %]', @ARGV );
763 [% appprefix %]_create.pl - Create a new Catalyst Component
767 [% appprefix %]_create.pl [options] model|view|controller name [helper] [options]
770 -help display this help and exits
773 [% appprefix %]_create.pl controller My::Controller
774 [% appprefix %]_create.pl view My::View
775 [% appprefix %]_create.pl view MyView TT
776 [% appprefix %]_create.pl view TT TT
777 [% appprefix %]_create.pl model My::Model
778 [% appprefix %]_create.pl model SomeDB CDBI dbi:SQLite:/tmp/my.db
779 [% appprefix %]_create.pl model AnotherDB CDBI dbi:Pg:dbname=foo root 4321
782 perldoc Catalyst::Manual
783 perldoc Catalyst::Manual::Intro
787 Create a new Catalyst Component.
791 Sebastian Riedel, C<sri\@oook.de>
795 Copyright 2004 Sebastian Riedel. All rights reserved.
797 This library is free software. You can redistribute it and/or modify
798 it under the same terms as perl itself.
805 use base 'Catalyst::Base';
809 [% class %] - Catalyst component
827 sub default : Private {
828 my ( $self, $c ) = @_;
829 $c->res->output('Congratulations, [% class %] is on Catalyst!');
840 This library is free software . You can redistribute it and/or modify
841 it under the same terms as perl itself.
848 use Test::More tests => 3;
849 use_ok( Catalyst::Test, '[% app %]' );
850 use_ok('[% class %]');
852 ok( request('[% uri %]')->is_success );
854 use Test::More tests => 1;
855 use_ok('[% class %]');