Roles
use CatalystX::Declare;
- component_role MyApp::Web::ControllerRole::Bar {
+ controller_role MyApp::Web::ControllerRole::Bar {
use MyApp::Types qw( Username );
class CatalystX::Declare extends MooseX::Declare is dirty {
+ use aliased 'CatalystX::Declare::Keyword::Model', 'ModelKeyword';
+ use aliased 'CatalystX::Declare::Keyword::View', 'ViewKeyword';
use aliased 'CatalystX::Declare::Keyword::Controller', 'ControllerKeyword';
use aliased 'CatalystX::Declare::Keyword::Role', 'RoleKeyword';
use aliased 'CatalystX::Declare::Keyword::Application', 'ApplicationKeyword';
around keywords {
$self->$orig,
- ControllerKeyword->new(identifier => 'controller'),
- RoleKeyword->new(identifier => 'controller_role'),
- ApplicationKeyword->new(identifier => 'application'),
+ ControllerKeyword->new( identifier => 'controller' ),
+ RoleKeyword->new( identifier => 'controller_role' ),
+ ApplicationKeyword->new( identifier => 'application' ),
+ ViewKeyword->new( identifier => 'view' ),
+ ModelKeyword->new( identifier => 'model' ),
}
}
$CLASS->config(name => 'My Declarative Web Application');
}
+See also:
+L<CatalystX::Declare::Keyword::Application>,
+L<MooseX::Declare/class>
+
=head2 Controllers
use CatalystX::Declare;
}
}
+See also:
+L<CatalystX::Declare::Keyword::Controller>,
+L<CatalystX::Declare::Keyword::Action>,
+L<CatalystX::Declare::Keyword::Component>,
+L<MooseX::Declare/class>
+
=head2 Roles
use CatalystX::Declare;
}
}
+See also:
+L<CatalystX::Declare::Keyword::Role>,
+L<CatalystX::Declare::Keyword::Action>,
+L<MooseX::Declare/class>
+
+=head2 Views
+
+ use CatalystX::Declare;
+
+ view MyApp::Web::View::TT
+ extends Catalyst::View::TT {
+
+ $CLASS->config(
+ TEMPLATE_EXTENSION => '.html',
+ );
+ }
+
+See also:
+L<CatalystX::Declare::Keyword::View>,
+L<CatalystX::Declare::Keyword::Component>,
+L<MooseX::Declare/class>
+
+=head2 Models
+
+ use CatalystX::Declare;
+
+ model MyApp::Web::Model::DBIC::Schema
+ extends Catalyst::Model::DBIC::Schema {
+
+ $CLASS->config(
+ schema_class => 'MyApp::Schema',
+ );
+ }
+
+See also:
+L<CatalystX::Declare::Keyword::Model>,
+L<CatalystX::Declare::Keyword::Component>,
+L<MooseX::Declare/class>
+
=head1 DESCRIPTION
B<This module is EXPERIMENTAL>
=item L<CatalystX::Declare::Keyword::Application>
-=item L<CatalystX::Declare::Keyword::Controller>
-
=item L<CatalystX::Declare::Keyword::Action>
+=item L<CatalystX::Declare::Keyword::Controller>
+
=item L<CatalystX::Declare::Keyword::Role>
+=item L<CatalystX::Declare::Keyword::View>
+
+=item L<CatalystX::Declare::Keyword::Model>
+
=back
Things like models, views, roles for request or response objects, can be built
--- /dev/null
+use MooseX::Declare;
+
+class CatalystX::Declare::Keyword::Component
+ extends MooseX::Declare::Syntax::Keyword::Class
+ with CatalystX::Declare::DefaultSuperclassing {
+
+
+ before add_namespace_customizations (Object $ctx, Str $package) {
+
+ $ctx->add_preamble_code_parts(
+ 'use CLASS',
+ );
+ }
+
+ method default_superclasses { 'Catalyst::Component' }
+}
+
+__END__
+
+=head1 NAME
+
+CatalystX::Declare::Keyword::Component - Declare Catalyst Components
+
+=head1 DESCRIPTION
+
+This handler provides common functionality for all component handlers.
+Please refer to the respective keyword handler documentation for more
+information:
+
+=over
+
+=item L<CatalystX::Declare::Keyword::Model>
+
+=item L<CatalystX::Declare::Keyword::View>
+
+=item L<CatalystX::Declare::Keyword::Controller>
+
+=back
+
+=head1 SUPERCLASSES
+
+=over
+
+=item L<MooseX::Declare::Syntax::Keyword::Class>
+
+=back
+
+=head1 ROLES
+
+=head1 METHODS
+
+These methods are implementation details. Unless you are extending or
+developing L<CatalystX::Declare>, you should not be concerned with them.
+
+=head2 add_namespace_customizations
+
+ Object->add_namespace_customizations (Object $ctx, Str $package)
+
+This will simply add L<CLASS> to the imported modules, to make C<CLASS>
+and C<$CLASS> available in the component.
+
+=head2 default_superclasses
+
+ List[Str] Object->default_superclasses ()
+
+Returns L<Catalyst::Component> as default superclass for components. The
+subclasses for other component keywords will usually want to override this.
+
+=head1 SEE ALSO
+
+=over
+
+=item L<CatalystX::Declare>
+
+=item L<CatalystX::Declare::Keyword::Model>
+
+=item L<CatalystX::Declare::Keyword::View>
+
+=item L<CatalystX::Declare::Keyword::Controller>
+
+=item L<MooseX::Declare/class>
+
+=back
+
+=head1 AUTHOR
+
+See L<CatalystX::Declare/AUTHOR> for author information.
+
+=head1 LICENSE
+
+This program is free software; you can redistribute it and/or modify it under
+the same terms as perl itself.
+
+=cut
use MooseX::Declare;
-class CatalystX::Declare::Keyword::Controller
- extends MooseX::Declare::Syntax::Keyword::Class
- with CatalystX::Declare::DefaultSuperclassing {
-
+class CatalystX::Declare::Keyword::Controller
+ extends CatalystX::Declare::Keyword::Component {
use MooseX::MethodAttributes ();
use aliased 'CatalystX::Declare::Keyword::Action', 'ActionKeyword';
before add_namespace_customizations (Object $ctx, Str $package) {
MooseX::MethodAttributes->init_meta(for_class => $package);
+
$ctx->add_preamble_code_parts(
- 'use CLASS',
['BEGIN',
sprintf('Class::MOP::load_class(q(%s))', TypeConstraintMapping),
sprintf('%s->meta->apply(%s->meta->meta)', TypeConstraintMapping, $package),
method auto_make_immutable { 0 }
+ around default_inner () {
+
+ my @modifiers = qw( );
+
+ return [
+ ( grep { my $id = $_->identifier; not grep { $id eq $_ } @modifiers } @{ $self->$orig() || [] } ),
+ ActionKeyword->new(identifier => 'action'),
+ ActionKeyword->new(identifier => 'under'),
+ ActionKeyword->new(identifier => 'final'),
+ ];
+ }
+
method add_with_option_customizations (Object $ctx, $package, ArrayRef $roles, HashRef $options) {
$ctx->add_cleanup_code_parts(
sprintf '%s->meta->make_immutable', $package
) unless $options->{is}{mutable};
}
-
- around default_inner () {
-
- my @modifiers = qw( );
-
- return [
- ( grep { my $id = $_->identifier; not grep { $id eq $_ } @modifiers } @{ $self->$orig() || [] } ),
- ActionKeyword->new(identifier => 'action'),
- ActionKeyword->new(identifier => 'under'),
- ActionKeyword->new(identifier => 'final'),
- ];
- }
}
__END__
=head1 DESCRIPTION
This handler module allows the declaration of Catalyst controllers. The
-C<controller> keyword is an extension of L<MooseX::Declare/class> with all the
+C<controller> keyword is an extension of the
+L<CatalystX::Declare::Keyword::Component>, which in turn is an extension
+of L<MooseX::Declare/class> with all the
bells and whistles, including C<extends>, C<with>, C<method> and modifier
declarations.
=over
-=item L<MooseX::Declare::Syntax::Keyword::Class>
-
-=back
-
-=head1 ROLES
-
-=over
-
-=item L<CatalystX::Declare::DefaultSuperclassing>
+=item L<CatalystX::Declare::Keyword::Component>
=back
Object->add_namespace_customizations (Object $ctx, Str $package)
This method modifier will initialise the controller with
-L<MooseX::MethodAttributes>, import L<CLASS> and add the
+L<MooseX::MethodAttributes> and add the
L<CatalystX::Declare::Controller::RegisterActionRoles> and
L<CatalystX::Declare::Controller::DetermineActionClass> controller roles
before calling the original.
Returns L<Catalyst::Controller> as the default superclass for all declared
controllers.
-=head2 auto_make_immutable
-
- Bool Object->auto_make_immutable ()
-
-Returns C<0>, indicating that L<MooseX::Declare> should not make this class
-immutable by itself. We will do that in the L</add_with_option_customizations>
-method ourselves.
-
=head2 add_with_option_customizations
Object->add_with_option_customizations (
This method will also add a callback to make the controller immutable to the
cleanup code parts unless C<is mutable> was specified.
+=head2 auto_make_immutable
+
+ Bool Object->auto_make_immutable ()
+
+Returns C<0>, indicating that L<MooseX::Declare> should not make this class
+immutable by itself. We will do that in the L</add_with_option_customizations>
+method ourselves.
+
=head2 default_inner
ArrayRef[Object] Object->default_inner ()
=item L<CatalystX::Declare::Keyword::Action>
+=item L<CatalystX::Declare::Keyword::Component>
+
=item L<MooseX::Declare/class>
=back
--- /dev/null
+use MooseX::Declare;
+
+class CatalystX::Declare::Keyword::Model
+ extends CatalystX::Declare::Keyword::Component {
+
+ method default_superclasses { 'Catalyst::Model' }
+}
+
+__END__
+
+=head1 NAME
+
+CatalystX::Declare::Keyword::Model - Declare Catalyst Models
+
+=head1 SYNOPSIS
+
+ use CatalystX::Declare;
+
+ model MyApp::Web::Model::Random {
+
+ method upto (Int $n) { int(rand $n) }
+ }
+
+=head1 DESCRIPTION
+
+This handler is a simple extension of L<CatalystX::Declare::Keyword::Component>
+and defaults to L<Catalyst::Model> as superclass. Additionally, L<CLASS> will
+be imported. See L<MooseX::Declare/class> for more information on usage, since
+this keyword is subclass extending its parent's features.
+
+=head1 SUPERCLASSES
+
+=over
+
+=item L<CatalystX::Declare::Keyword::Component>
+
+=back
+
+=head1 METHODS
+
+These methods are implementation details. Unless you are extending or
+developing L<CatalystX::Declare>, you should not be concerned with them.
+
+=head2 default_superclasses
+
+ List[Str] Object->default_superclasses ()
+
+Defaults to L<Catalyst::View>.
+
+=head1 SEE ALSO
+
+=over
+
+=item L<CatalystX::Declare>
+
+=item L<CatalystX::Declare::Keyword::Component>
+
+=item L<MooseX::Declare/class>
+
+=back
+
+=head1 AUTHOR
+
+See L<CatalystX::Declare/AUTHOR> for author information.
+
+=head1 LICENSE
+
+This program is free software; you can redistribute it and/or modify it under
+the same terms as perl itself.
+
+=cut
--- /dev/null
+use MooseX::Declare;
+
+class CatalystX::Declare::Keyword::View
+ extends CatalystX::Declare::Keyword::Component {
+
+ method default_superclasses { 'Catalyst::View' }
+}
+
+__END__
+
+=head1 NAME
+
+CatalystX::Declare::Keyword::View - Declare Catalyst Views
+
+=head1 SYNOPSIS
+
+ use CatalystX::Declare;
+
+ view MyApp::Web::View::Example
+ extends Catalyst::View::TT
+ with MyApp::Web::ViewRole::Caching {
+
+ after process (Object $ctx) {
+ $ctx->log->debug('done processing at ' . time)
+ if $ctx->debug;
+ }
+ }
+
+=head1 DESCRIPTION
+
+This handler is a direct extension of L<CatalystX::Declare::Keyword::Component>
+and provides a C<view> keyword to declare a catalyst view. Currently, the only
+things this declaration does is setting up a L<Moose> class like
+L<MooseX::Declare> does, provide L<CLASS> to its scope and default the
+superclass to L<Catalyst::View>.
+
+See L<MooseX::Declare/class> for more information on this kind of keyword.
+Since views do not take actions, no special handling of roles is required,
+other than with controller roles. So if you want to write roles for views,
+simply use the L<MooseX::Declare/role> syntax.
+
+=head1 SUPERCLASSES
+
+=over
+
+=item L<CatalystX::Declare::Keyword::Component>
+
+=back
+
+=head1 METHODS
+
+These methods are implementation details. Unless you are extending or
+developing L<CatalystX::Declare>, you should not be concerned with them.
+
+=head2 default_superclasses
+
+ List[Str] Object->default_superclasses ()
+
+Defaults to L<Catalyst::View>.
+
+=head1 SEE ALSO
+
+=over
+
+=item L<CatalystX::Declare>
+
+=item L<CatalystX::Declare::Keyword::Component>
+
+=item L<MooseX::Declare/class>
+
+=back
+
+=head1 AUTHOR
+
+See L<CatalystX::Declare/AUTHOR> for author information.
+
+=head1 LICENSE
+
+This program is free software; you can redistribute it and/or modify it under
+the same terms as perl itself.
+
+=cut
--- /dev/null
+#!/usr/bin/env perl
+use strict;
+use warnings;
+
+use FindBin;
+use lib "$FindBin::Bin/lib";
+
+use Test::More;
+use Catalyst::Test 'TestApp';
+
+is get('/view_test/normal'), 'view rendered', 'normal view rendering';
+is get('/view_test/role_test'), 'view rendered modified', 'view role changed rendering';
+
+
+done_testing;
--- /dev/null
+#!/usr/bin/env perl
+use strict;
+use warnings;
+
+use FindBin;
+use lib "$FindBin::Bin/lib";
+
+use Test::More;
+use Catalyst::Test 'TestApp';
+
+my $counter = 1;
+
+is get('/model_test/next'), $counter++, 'modifying model'
+ for 1 .. 3;
+
+
+done_testing;
--- /dev/null
+use CatalystX::Declare;
+
+controller TestApp::Controller::ModelTest {
+
+ method find_model (Object $ctx) {
+ return $ctx->component('Model::TestModel');
+ }
+
+
+ action base as 'model_test' under '/';
+
+ under base {
+
+ final action next {
+ $ctx->response->body( $self->find_model($ctx)->next );
+ }
+
+ final action reset {
+ $ctx->response->body( $self->find_model($ctx)->reset );
+ }
+ }
+}
--- /dev/null
+use CatalystX::Declare;
+
+controller TestApp::Controller::ViewTest {
+
+ action base as 'view_test' under '/';
+
+ under base {
+
+ final action normal;
+
+ final action role_test {
+ $ctx->stash(role_tag => 'modified');
+ }
+ }
+
+ action end {
+ $ctx->forward( 'View::TestView' );
+ }
+}
--- /dev/null
+use CatalystX::Declare;
+
+model TestApp::Model::TestModel {
+
+ use MooseX::Types::Moose qw( Int );
+
+ has counter => (
+ is => 'rw',
+ isa => Int,
+ required => 1,
+ default => 0,
+ );
+
+ method next {
+ $self->counter( $self->counter + 1 );
+ return $self->counter;
+ }
+
+ method reset {
+ $self->counter(0);
+ return 'reset';
+ }
+}
--- /dev/null
+use CatalystX::Declare;
+
+view TestApp::View::TestView
+ with TestApp::ViewRole::TestRole {
+
+ method render (Object $ctx) {
+ return 'view rendered';
+ }
+
+ method process (Object $ctx) {
+ $ctx->response->body( $self->render($ctx) );
+ }
+}
--- /dev/null
+use MooseX::Declare;
+
+role TestApp::ViewRole::TestRole {
+
+ around render (Object $ctx) {
+
+ if (my $tag = $ctx->stash->{role_tag}) {
+ return join ' ' => $self->$orig($ctx), $tag;
+ }
+
+ return $self->$orig($ctx);
+ }
+}