=head1 NAME Reaction::Manual::Intro - Introduction to Reaction =head1 INTRODUCTION Reaction is basically an extended MVC: =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 =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 into a set of Interface Models which can be used by Reaction to build the interface components. If you're not familiar with L or don't have a schema handy, now is a good time to go through L 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; class IM is 'Catalyst::Model::Reaction::InterfaceModel::DBIC', which { }; 1; =head2 Controllers =head3 Root controller Your Reaction application must have a Root controller which inherits from C. 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 => '' ); 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', 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; class TT is 'Reaction::UI::View::TT', which { }; 1; __END__; XX TODO =head1 SEE ALSO =over =item * L =item * L =back =head1 AUTHORS See L for authors. =head1 LICENSE See L for the license. =cut