Grid->field_labels as rw attr
[catagits/Reaction.git] / lib / Reaction / Manual / Intro.pod
1 =head1 NAME
2
3 Reaction::Manual::Intro - Introduction to Reaction
4
5 =head1 INTRODUCTION
6
7 Reaction is basically an extended MVC:
8
9 =over
10
11 =item Domain Model 
12
13 DBIx::Class::Schema, MyApp::Foo, MyApp::Bar, etc.
14
15 =item Interface Model 
16
17 InterfaceModel::DBIC::Schema, InterfaceModel::Action,
18 MyApp::InterfaceModel::Foo classes.
19
20 =item Controller 
21
22 Mediation and navigation.
23
24 =item ViewPort
25
26 Event handling encapsulation.
27
28 =item Widget
29
30 View logic.
31
32 =item Renderer 
33
34 MyApp::View:: classes, renders viewports.
35
36 =back
37
38 =head1 THE REACTION WAY
39
40 The idea is you separate your domain model, which encapsulates the domain
41 itself from your interface model, which is a model of how a particular app or
42 class of apps interact with that domain and provides objects/methods to
43 encapsulate the common operations it does.
44
45 =head2 Domain Models vs Interface Models
46
47 Domain models are expected to drive the application business logic and data.
48 All domain models that need to be effectively displayed somehow at the user
49 interface (a table, for instance) must interact with an interface model.
50 These should provide the common methods needed in order to carry out
51 user-generated events.
52
53 =head1 SETTING UP A REACTION APPLICATION
54
55 Reaction applications are set up just like Catalyst:
56
57     $ catalyst.pl MyApp
58     # output ommited
59     $ cd MyApp
60
61 =head2 Models
62
63 Reaction provides a reflector component which automagically
64 maps a L<DBIx::Class::Schema> into a set of Interface Models which can be used
65 by Reaction to build the interface components. If you're not familiar with
66 L<DBIx::Class> or don't have a schema handy, now is a good time to go through
67 L<DBIx::Class::Manual::Intro> to get a schema set up.
68
69 It is important that your Result-objects implement the meta-protocol of Moose
70 One way to achive that is to do the following:
71
72     package MyApp::Schema::Result::Bar;
73     use base 'DBIx::Class';
74     use Moose;
75     
76     has 'name' => (isa => 'Str', required => 1, rw => 1);
77     
78     use namespace::clean -except => [ 'meta' ];
79     
80     __PACKAGE__->load_components(qw(Core));
81     __PACKAGE__->table('bar');
82     __PACKAGE__->add_columns(
83         name => {
84             data_type   => 'varchar',
85             size        => 255,
86             is_nullable => 0,
87         }
88     );
89     __PACKAGE__->primary_key('name');
90     1;
91     
92 Once you have your schema set up like that, you can create the InferfaceModel:
93
94     package MyApp::InterfaceModel::DBIC;
95
96     use base 'Reaction::InterfaceModel::Object';
97     use Reaction::InterfaceModel::Reflector::DBIC;
98
99     my $reflector = Reaction::InterfaceModel::Reflector::DBIC->new;
100
101     $reflector->reflect_schema(
102          model_class  => __PACKAGE__,
103          schema_class => 'MyApp::Schema',
104          sources => [qw/Foo Baz/],
105     );
106
107     1;
108
109 Then you create a MyApp::Model that uses this InferfaceModel:
110
111     package Myapp::Model::IM;
112     
113     use Reaction::Class;
114     
115     extends 'Catalyst::Model::Reaction::InterfaceModel::DBIC';
116
117     1;
118     
119 =head2 Controllers
120
121 =head3 Root controller
122
123 Your Reaction application must have a Root controller which inherits from
124 C<Reaction::UI::Controller::Root>.
125
126     package MyApp::Controller::Root;
127
128     use warnings;
129     use strict;
130     use base qw/Reaction::UI::Controller::Root/;
131
132     __PACKAGE__->config(
133         view_name => 'Site',
134         window_title => 'My Reaction App',
135         namespace => ''
136     );
137
138     sub base : Chained('/') PathPart('') CaptureArgs(0) {
139         # do some setup for every request
140         # also provides a chain root for other controllers to use
141     }
142
143     1;
144
145 =head3 Individual controllers
146
147 For each Collection(table?) in your DB, you need to create a controller
148
149     package MyApp::Controller::Foo;
150
151     use base 'Reaction::UI::Controller::Collection::CRUD';
152     use Reaction::Class;
153
154     __PACKAGE__->config(
155       model_name => 'IM',   # This corresponds to the name of the MyApp::Model you created earlier
156       collection_name => 'Foo', # Name of one of the sources in your InterfaceModel
157       action => {
158         base => { Chained => '/base',  # chain to the base action in the root controller
159                   PathPart => 'foo' },
160       },
161     );
162
163     1;
164     
165 XX TODO
166
167 =head2 View
168
169 One of the views in your application should look something like this:
170
171     package MyApp::View::TT;
172
173     use Reaction::Class;
174
175     extends 'Reaction::UI::View::TT';
176
177     1;
178
179     __END__;
180
181     
182 XX TODO
183
184 =head1 SEE ALSO
185
186 =over 
187
188 =item * L<Reaction::Manual::Cookbook>
189
190 =item * L<Reaction::Manual::FAQ>
191
192 =back
193
194 =head1 AUTHORS
195
196 See L<Reaction::Class> for authors.
197
198 =head1 LICENSE
199
200 See L<Reaction::Class> for the license.
201
202 =cut