diff options
author | edenc <edenc@03d0b0b2-0e1a-0410-a411-fdb2f4bd65d7> | 2008-10-10 22:18:59 +0000 |
---|---|---|
committer | edenc <edenc@03d0b0b2-0e1a-0410-a411-fdb2f4bd65d7> | 2008-10-10 22:18:59 +0000 |
commit | cc4f29bff386a4b13da39d10ceb49d31d7eb07d0 (patch) | |
tree | 5f589da19397763bd440571a27b7701a5ceb0639 /lib/Reaction/Manual | |
parent | 7b6797a0a3660459fbaef5afec5aa8022416f313 (diff) | |
download | reaction-cc4f29bff386a4b13da39d10ceb49d31d7eb07d0.tar.gz reaction-cc4f29bff386a4b13da39d10ceb49d31d7eb07d0.zip |
doc patches from clwolfe
Diffstat (limited to 'lib/Reaction/Manual')
-rw-r--r-- | lib/Reaction/Manual/Clipboard.pod | 191 | ||||
-rw-r--r-- | lib/Reaction/Manual/Glossary.pod | 53 | ||||
-rw-r--r-- | lib/Reaction/Manual/Intro.pod | 206 | ||||
-rw-r--r-- | lib/Reaction/Manual/Troubleshooting.pod | 6 |
4 files changed, 299 insertions, 157 deletions
diff --git a/lib/Reaction/Manual/Clipboard.pod b/lib/Reaction/Manual/Clipboard.pod new file mode 100644 index 0000000..1a9d3e7 --- /dev/null +++ b/lib/Reaction/Manual/Clipboard.pod @@ -0,0 +1,191 @@ +=head1 NAME + +Reaction::Manual::Clipboard - snippets of Reaction docs + + + +=head2 These should probably go in the glossary. + +=over + +=item Domain Model + +DBIx::Class::Schema, MyApp::Foo, MyApp::Bar, etc. + +=item Interface Model + +InterfaceModel::DBIC::Schema, InterfaceModel::Action, +MyApp::InterfaceModel::Foo classes. + +=item Controller + +Mediation and navigation. + +=item ViewPort + +Event handling encapsulation. + +=item Widget + +View logic. + +=item Renderer + +MyApp::View:: classes, renders viewports. + +=back + + +These should go in the tutorial? + + +=head1 SETTING UP A REACTION APPLICATION + +Reaction applications are set up just like Catalyst: + + $ catalyst.pl MyApp + # output ommited + $ cd MyApp + +=head2 Models + +Reaction provides a reflector component which automagically +maps a L<DBIx::Class::Schema> into a set of Interface Models which can be used +by Reaction to build the interface components. If you're not familiar with +L<DBIx::Class> or don't have a schema handy, now is a good time to go through +L<DBIx::Class::Manual::Intro> to get a schema set up. + +It is important that your Result-objects implement the meta-protocol of Moose +One way to achive that is to do the following: + + package MyApp::Schema::Result::Bar; + use base 'DBIx::Class'; + use Moose; + + has 'name' => (isa => 'Str', required => 1, rw => 1); + + use namespace::clean -except => [ 'meta' ]; + + __PACKAGE__->load_components(qw(Core)); + __PACKAGE__->table('bar'); + __PACKAGE__->add_columns( + name => { + data_type => 'varchar', + size => 255, + is_nullable => 0, + } + ); + __PACKAGE__->primary_key('name'); + 1; + +Once you have your schema set up like that, you can create the InferfaceModel: + + package MyApp::InterfaceModel::DBIC; + + use base 'Reaction::InterfaceModel::Object'; + use Reaction::InterfaceModel::Reflector::DBIC; + + my $reflector = Reaction::InterfaceModel::Reflector::DBIC->new; + + $reflector->reflect_schema( + model_class => __PACKAGE__, + schema_class => 'MyApp::Schema', + sources => [qw/Foo Baz/], + ); + + 1; + +Then you create a MyApp::Model that uses this InferfaceModel: + + package Myapp::Model::IM; + + use Reaction::Class; + + extends 'Catalyst::Model::Reaction::InterfaceModel::DBIC'; + + 1; + +=head2 Controllers + +=head3 Root controller + +Your Reaction application must have a Root controller which inherits from +C<Reaction::UI::Controller::Root>. + + package MyApp::Controller::Root; + + use warnings; + use strict; + use base qw/Reaction::UI::Controller::Root/; + + __PACKAGE__->config( + view_name => 'Site', + window_title => 'My Reaction App', + namespace => '' + ); + + sub base : Chained('/') PathPart('') CaptureArgs(0) { + # do some setup for every request + # also provides a chain root for other controllers to use + } + + 1; + +=head3 Individual controllers + +For each Collection(table?) in your DB, you need to create a controller + + package MyApp::Controller::Foo; + + use base 'Reaction::UI::Controller::Collection::CRUD'; + use Reaction::Class; + + __PACKAGE__->config( + model_name => 'IM', # This corresponds to the name of the MyApp::Model you created earlier + collection_name => 'Foo', # Name of one of the sources in your InterfaceModel + action => { + base => { Chained => '/base', # chain to the base action in the root controller + PathPart => 'foo' }, + }, + ); + + 1; + +XX TODO + +=head2 View + +One of the views in your application should look something like this: + + package MyApp::View::TT; + + use Reaction::Class; + + extends 'Reaction::UI::View::TT'; + + 1; + + __END__; + + +XX TODO + +=head1 SEE ALSO + +=over + +=item * L<Reaction::Manual::Cookbook> + +=item * L<Reaction::Manual::FAQ> + +=back + +=head1 AUTHORS + +See L<Reaction::Class> for authors. + +=head1 LICENSE + +See L<Reaction::Class> for the license. + +=cut diff --git a/lib/Reaction/Manual/Glossary.pod b/lib/Reaction/Manual/Glossary.pod new file mode 100644 index 0000000..21480e8 --- /dev/null +++ b/lib/Reaction/Manual/Glossary.pod @@ -0,0 +1,53 @@ +=head1 NAME + +Reaction::Manual::Glossary - Terms and Definitions used in Reaction + +=head1 GLOSSARY + +=head3 Controller + +=head3 Domain Model + +=head3 Interface Model + +=head3 ListView + +=head3 MVC + +Model-View-Controller - a high-level software design pattern, which focuses on separation of concerns. For details on MVC, try here, here, and here. Reaction is an extended MVC system; it uses a two-layer Model (the Interface Model, with the Domain Model below it). Views are implemented by DOCTODO. Controllers are represented by DOCTODO. + +=head3 Observer + +A software design pattern in which one + +=head3 Role + +A particular interface that a class implements. Here, Role is used in the sense of Moose::Role; this same concept is sometimes called a Mix-In Class or a Decorator pattern. + +=head3 View + +In Reaction, the View modules handle rendering the ViewPort. ViewPorts are the V in MVC. + +=head3 ViewPort + + + +=head3 Widget + +=head1 SEE ALSO + +=over + +=item * L<Reaction::Manual> + +=back + +=head1 AUTHORS + +See L<Reaction::Class> for authors. + +=head1 LICENSE + +See L<Reaction::Class> for the license. + +=cut diff --git a/lib/Reaction/Manual/Intro.pod b/lib/Reaction/Manual/Intro.pod index b761012..cc868cf 100644 --- a/lib/Reaction/Manual/Intro.pod +++ b/lib/Reaction/Manual/Intro.pod @@ -2,184 +2,76 @@ Reaction::Manual::Intro - Introduction to Reaction -=head1 INTRODUCTION +=head1 SYNOPSIS -Reaction is basically an extended MVC: + Moose + Catalyst + Layered Models = eternal happiness -=over +=head1 MOTIVATION -=item Domain Model +While L<Catalyst> is a very powerful and flexible web app +framework, many pieces end up being recoded for each +new application: user interfaces, in particular. -DBIx::Class::Schema, MyApp::Foo, MyApp::Bar, etc. +Meanwhile, advances in Perl metaprogramming (especially L<Moose>) +have opened up new possibilities in terms of introspection. +Why not build user interfaces based on class metadata? +This would allow the user interface templates to be very general +where possible. -=item Interface Model +Thus, Reaction is basically an extended MVC framework, which +leverages class metadata to reduce or eliminate UI coding. -InterfaceModel::DBIC::Schema, InterfaceModel::Action, -MyApp::InterfaceModel::Foo classes. +But it's much more.... -=item Controller +=head1 DOMAIN MODELS AND INTERFACE MODELS -Mediation and navigation. +Many programmers are now comfortable using ORMs of one sort or +another - L<DBIx::Class>, L<Class::DBI>, Hibernate, etc. These systems +are wonderful for bridging from the world of OO into the world of relational +databases (or other datastores). This model is sometimes called a +"domain model", because it models the "nouns" of a problem domain in +the real world. Domain models are easily shared accross applications, +and can enforce validation and other integrity constraints. -=item ViewPort +However, over time, many application developers find themselves adding +business logic to the domain model. This business logic is often +application-specific, and reduces the reusability of the domain model. +Worse, business logic becomes spread between the model and the contoller. -Event handling encapsulation. +Reaction adds another layer, the Interface Model. Interface models provide an +adaptor to the domain model, customized for a particular application (or group +of use cases). This decouples the domain model from the application, +allowing it to be reused more freely. Additionally, the Interface Model +becomes the natural location for business logic. -=item Widget +Happily, Reaction again uses reflection to make the degenerate case easy - when your +IM has no customized functionality, it can simply delegate all work to the DM. When +you need to add custom business logic, you can add or replace functionality as needed. -View logic. +The DM/IM split is sometimes referred to as a FacadeModel - see L<http://www.twinforces.com/tf/docs/MFCV.html>, for example. -=item Renderer +=head1 WHAT YOU'LL NEED TO KNOW -MyApp::View:: classes, renders viewports. +Reaction is based on the L<Catalyst> web application framework. You'll certainly +need to be familiar with L<Catalyst::Manual::Intro>. -=back - -=head1 THE REACTION WAY - -The idea is you separate your domain model, which encapsulates the domain -itself from your interface model, which is a model of how a particular app or -class of apps interact with that domain and provides objects/methods to -encapsulate the common operations it does. - -=head2 Domain Models vs Interface Models - -Domain models are expected to drive the application business logic and data. -All domain models that need to be effectively displayed somehow at the user -interface (a table, for instance) must interact with an interface model. -These should provide the common methods needed in order to carry out -user-generated events. - -=head1 SETTING UP A REACTION APPLICATION - -Reaction applications are set up just like Catalyst: - - $ catalyst.pl MyApp - # output ommited - $ cd MyApp - -=head2 Models - -Reaction provides a reflector component which automagically -maps a L<DBIx::Class::Schema> into a set of Interface Models which can be used -by Reaction to build the interface components. If you're not familiar with -L<DBIx::Class> or don't have a schema handy, now is a good time to go through -L<DBIx::Class::Manual::Intro> to get a schema set up. - -It is important that your Result-objects implement the meta-protocol of Moose -One way to achive that is to do the following: - - package MyApp::Schema::Result::Bar; - use base 'DBIx::Class'; - use Moose; - - has 'name' => (isa => 'Str', required => 1, rw => 1); - - use namespace::clean -except => [ 'meta' ]; - - __PACKAGE__->load_components(qw(Core)); - __PACKAGE__->table('bar'); - __PACKAGE__->add_columns( - name => { - data_type => 'varchar', - size => 255, - is_nullable => 0, - } - ); - __PACKAGE__->primary_key('name'); - 1; - -Once you have your schema set up like that, you can create the InferfaceModel: - - package MyApp::InterfaceModel::DBIC; - - use base 'Reaction::InterfaceModel::Object'; - use Reaction::InterfaceModel::Reflector::DBIC; - - my $reflector = Reaction::InterfaceModel::Reflector::DBIC->new; - - $reflector->reflect_schema( - model_class => __PACKAGE__, - schema_class => 'MyApp::Schema', - sources => [qw/Foo Baz/], - ); - - 1; - -Then you create a MyApp::Model that uses this InferfaceModel: - - package Myapp::Model::IM; - - use Reaction::Class; - - extends 'Catalyst::Model::Reaction::InterfaceModel::DBIC'; - - 1; - -=head2 Controllers - -=head3 Root controller - -Your Reaction application must have a Root controller which inherits from -C<Reaction::UI::Controller::Root>. - - package MyApp::Controller::Root; - - use warnings; - use strict; - use base qw/Reaction::UI::Controller::Root/; - - __PACKAGE__->config( - view_name => 'Site', - window_title => 'My Reaction App', - namespace => '' - ); - - sub base : Chained('/') PathPart('') CaptureArgs(0) { - # do some setup for every request - # also provides a chain root for other controllers to use - } - - 1; - -=head3 Individual controllers - -For each Collection(table?) in your DB, you need to create a controller - - package MyApp::Controller::Foo; - - use base 'Reaction::UI::Controller::Collection::CRUD'; - use Reaction::Class; - - __PACKAGE__->config( - model_name => 'IM', # This corresponds to the name of the MyApp::Model you created earlier - collection_name => 'Foo', # Name of one of the sources in your InterfaceModel - action => { - base => { Chained => '/base', # chain to the base action in the root controller - PathPart => 'foo' }, - }, - ); - - 1; - -XX TODO - -=head2 View - -One of the views in your application should look something like this: +Currently, only L<DBIx::Class> is supported as a domain model. At least basic +familiarity will be needed. L<DBIx::Class::Manual::Intro> is a good starting point. - package MyApp::View::TT; +The default view renderer is L<Template::Toolkit>. To edit your views, you'll +need to know something about it. - use Reaction::Class; +While you don't need to know L<Moose> directly, a lot of the concepts of +metaprogramming will keep coming up as you work with Reaction. +Thus, getting to know L<Moose> will serve you well. - extends 'Reaction::UI::View::TT'; +=head1 NEXT STEPS - 1; +If you'd like an example, see L<Reaction::Manual::Example>. - __END__; +If you're ready to dive in and start learning step by step, see L<Reaction::Manual::Tutorial>. - -XX TODO +As you encounter unfamiliar terms, or want to see how a particular term is used in the context of the Reaction project, refer to the L<Reaction::Manual::Glossary>. =head1 SEE ALSO diff --git a/lib/Reaction/Manual/Troubleshooting.pod b/lib/Reaction/Manual/Troubleshooting.pod index db850bf..b24bcd0 100644 --- a/lib/Reaction/Manual/Troubleshooting.pod +++ b/lib/Reaction/Manual/Troubleshooting.pod @@ -18,3 +18,9 @@ You have to run the extends at compile time for perl attributes to work: Welcome to hating attributes. =cut + +=begin docnotes + +clwolfe - suggest moving this to FAQ + +=end |