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.