Arthur Axel "fREW" Schmidt
Autumn Equinox 2011
$c->model('DB')
$c->view('TT')
$c->request
$c->response
sub add_user : Local { ... }
sub home : Global { ... }
sub add_friend : Path('add_buddy') { ... }
sub about : Path('/about') { ... }
sub load_users : Chained('/') PathPart('users') CaptureArgs(0) { ... }
sub users : Chained('load_users') PathPart('') Args(0) { ... }
sub load_user : Chained('load_users') PathPart('') CaptureArgs(1) { ... }
sub user : Chained('load_user') PathPart('') Args(0) { ... }
sub load_roles : Chained('load_user') PathPart('roles') CaptureArgs(0) { ... }
sub roles : Chained('load_roles') PathPart('') Args(0) { ... }
package MyApp::Controller::Users; # ... sub load_users : Chained('/') PathPart('users') CaptureArgs(0) { ... } sub users : Chained('load_users') PathPart('') Args(0) { ... } sub load_user : Chained('load_users') PathPart('') CaptureArgs(1) { ... } sub user : Chained('load_user') PathPart('') Args(0) { ... }
package MyApp::Controller::Users::Roles; # ... sub load_roles : Chained('/users/load_users') PathPart('roles') CaptureArgs(0) { ... } sub roles : Chained('load_roles') PathPart('') Args(0) { ... }
__PACKAGE__->config( actions => { load_users => { Chained => '/', PathPart => 'users', CaptureArgs => 0 }, load_user => { Chained => 'load_users', PathPart => 'user', CaptureArgs => 1 }, load_roles => { Chained => 'load_user', PathPart => 'roles', CaptureArgs => 0 }, users => { Chained => 'load_users', PathPart => '', Args => 0 }, user => { Chained => 'load_user', PathPart => '', Args => 0 }, roles => { Chained => 'load_roles', PathPart => '', Args => 0 }, }, ); sub load_users { ... } sub users { ... } sub load_user { ... } sub user { ... } sub load_roles { ... } sub roles { ... }
with 'Lynx::TraitFor::Controller::RunMethod'; __PACKAGE__->config( go_prefix => 'configure', actions => { go => { Chained => '/currentuser/shareddashboards/gadgets/item', PathPart => 'configure', }, }, );
sub users : Local ActionClass('REST') {}
sub users_GET { ... } # GET /foo/users # GET /foo/users/1 # GET /foo/users/1/2/3/4/5 sub users_POST :Args(0) { ... } # POST /foo/users sub users_PUT :Args(1) { ... } # PUT /foo/users/1 sub users_DELETE :Args(1) { ... } # DELETE /foo/users/1
sub base : Chained('/') PathPart('users') { ... }
sub users : Chained('base') PathPart('') ActionClass('REST') {}
sub users_GET { ... } # GET /users sub users_POST { ... } # POST /users
sub item : Chained('base') PathPart('') CatpureArgs(1) { ... }
sub user : Chained('item') PathPart('')ActionClass('REST') {}
sub user_GET { ... } # GET /users/1 sub user_PUT { ... } # PUT /users/1 sub user_DELETE { ... } # DELETE /users/1
$c->stash->{+__PACKAGE__}{foo}
$c->stash->{'MyApp::Controller::Users'}{foo}
package Lynx::SMS::Controller::Accounts; use Moose; use namespace::autoclean; use syntax 'method'; BEGIN { extends 'Lynx::SMS::RESTController' }; with 'Catalyst::TraitFor::Controller::DBIC::DoesPaging', 'Catalyst::TraitFor::Controller::DoesExtPaging'; sub base : Chained('/') PathPart('accounts') CaptureArgs(0) { my ($self, $c) = @_; $c->stash->{+__PACKAGE__}{rs} = $c->model('DB::Account'); } sub item : Chained('base') PathPart('') CaptureArgs(1) { my ($self, $c, $id) = @_; $c->stash->{+__PACKAGE__}{id} = $id; $c->stash->{+__PACKAGE__}{thing} = $c->stash->{+__PACKAGE__}{rs}->find($id); } sub accounts :Chained('base') PathPart('') Args(0) ActionClass('REST') {} method accounts_POST($c) : RequiresRole('write') { my $params = $c->request->data->{data}; my $foo = $c->stash->{+__PACKAGE__}{rs}->create($params); $c->stash->{rest} = { success => 1, data => $foo }; } method accounts_GET($c) : RequiresRole('read') { $c->stash->{rest} = $self->ext_paginate( $self->search($c, $self->paginate($c, $self->sort($c, $c->stash->{+__PACKAGE__}{rs}) ) ) ); } sub account :Chained('item') PathPart('') Args(0) ActionClass('REST') {} method account_GET($c) : RequiresRole('read') { $c->stash->{rest} = { success => 1, data => $c->stash->{+__PACKAGE__}{thing}, }; } method account_PUT($c) : RequiresRole('write') { my $foo = $c->stash->{+__PACKAGE__}{thing}; my $params = $c->request->data->{data}; $foo->update($params); $c->stash->{rest} = { success => 1, data => $foo }; } method account_DELETE($c) : RequiresRole('delete') { $c->stash->{+__PACKAGE__}{rs}->search({ id => $c->stash->{+__PACKAGE__}{id}, })->delete; $c->stash->{rest} = { success => 1 }; }
log4perl.rootLogger=ALL, SCREEN, LOGFILE log4perl.appender.SCREEN=Log::Log4perl::Appender::Screen log4perl.appender.SCREEN.utf8=1 log4perl.appender.SCREEN.layout=PatternLayout log4perl.appender.SCREEN.layout.ConversionPattern=<%c> [%p] %m%n log4perl.appender.LOGFILE=Log::Log4perl::Appender::File log4perl.appender.LOGFILE.filename=/var/log/myerrs.log log4perl.appender.LOGFILE.mode=append log4perl.filter.important = Log::Log4perl::Filter::LevelRange log4perl.filter.important.LevelMin = WARN log4perl.filter.important.LevelMax = FATAL log4perl.filter.important.AcceptOnMatch = true log4perl.filter.catalyst = sub { my %p = @_; $p{log4p_category} =~ /^catalyst/i } log4perl.filter.not_important_catalyst = Log::Log4perl::Filter::Boolean log4perl.filter.not_important_catalyst.logic = !catalyst || important
# MyApp/Util.pm sub init_logger { require Log::Log4perl; require Log::Contextual; Log::Log4perl->init_and_watch('lynx_sms_logger.conf'); Log::Contextual::set_logger(sub { Log::Log4perl::get_logger($_[0]) }); }
# script.pl use MyApp::Util; MyApp::Util::init_logger();
# MyApp.pm unless (__PACKAGE__->debug) { require Log::Log4perl; require Try::Tiny; if (Try::Tiny::try { Log::Log4perl::get_logger() }) { no strict 'refs'; *log = sub { Log::Log4perl::get_logger(scalar caller) } } }
# t/lib/MyApp/Test.pm sub as_psgi { my $app; if (Lynx::Util::mode() eq 'live') { plan skip_all => 'Set the LIVE_TEST_SERVER envvar to run live tests' unless $ENV{LIVE_TEST_SERVER}; require Plack::App::Proxy; $app = Plack::App::Proxy ->new( remote => "http://$ENV{LIVE_TEST_SERVER}" ) ->to_app; } else { require Lynx; require Plack::Builder; require Plack::App::File; my $builder = Plack::Builder->new; $builder->mount('/app' => Lynx->psgi_app); $builder->mount('/' => Plack::App::File->new(root => ".")->to_app); $app = $builder; } return $app }
my $mech = Test::WWW::Mechanize::PSGI->new( app => $app ); $mech->get( "/cgi/logon.plx?UserID=test&Password=test" ); $mech->content_lacks( 'Login Error', 'Login should succeed'); $mech->content_lacks( 'ODBC Error', 'No DB error');
around dispatch => sub { my ($orig, $self, @args) = (@_); return $self->model('DB')->txn_do(sub { $self->$orig(@args) }); };
around dispatch => sub { my ($orig, $self, @args) = (@_); my $dir = $self->model('DB')->schema->kiokudb_handle; return $dir->txn_do( scope => 1, body => sub { $self->$orig(@args) }, ); };
# in MyApp.pm use CatalystX::RoleApplicator; __PACKAGE__->apply_request_class_roles(qw[ Catalyst::TraitFor::Request::REST::ForBrowsers ]);
# in action if ($c->request->looks_like_browser) { ... }
# in MyApp.pm use CatalystX::InjectComponent; after setup_components => sub { my $class = shift; CatalystX::InjectComponent->inject( into => $class, component => 'Lynx::Debug::Controller::Login::As', ) } if Lynx::Util::mode() eq 'dev';
use Catalyst::Controller::Accessors; cat_has user => ( is => 'ro', namespace => 'Lynx::Controller::User', ); cat_has role => ( is => 'rw' );
# in action sub role { my ($self, $c, $id) = @_; $self->role($c, $self->user($c)->roles->find($id) ); # ... }
/
#