NAME
Reaction::Manual::Intro - Introduction to Reaction
INTRODUCTION
Reaction is basically an extended MVC:
- Domain Model
-
DBIx::Class::Schema, MyApp::Foo, MyApp::Bar, etc.
- Interface Model
-
InterfaceModel::DBIC::Schema, InterfaceModel::Action, MyApp::InterfaceModel::Foo classes.
- Controller
-
Mediation and navigation.
- ViewPort
-
Event handling encapsulation.
- Widget
-
View logic.
- Renderer
-
MyApp::View:: classes, renders viewports.
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.
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.
SETTING UP A REACTION APPLICATION
Reaction applications are set up just like Catalyst:
$ catalyst.pl MyApp
# output ommited
$ cd MyApp
Models
Reaction provides a reflector component which automagically maps a 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 DBIx::Class or don't have a schema handy, now is a good time to go through 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;
class IM is 'Catalyst::Model::Reaction::InterfaceModel::DBIC', which {
};
1;
Controllers
Root controller
Your Reaction application must have a Root controller which inherits from 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 => ''
);
1;
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
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
SEE ALSO
AUTHORS
See Reaction::Class for authors.
LICENSE
See Reaction::Class for the license.