Commit | Line | Data |
63bb30b4 |
1 | =head1 NAME |
2 | |
3 | Reaction::Manual::Overview - Orientation in Reaction |
4 | |
5 | =head1 DESCRIPTION |
6 | |
7 | This document aims at describing the modular parts of L<Reaction> and explain |
8 | how they are tied together. |
9 | |
10 | =head1 APPLICATION |
11 | |
12 | A Reaction application is really a L<Catalyst> application under the hood. Reaction |
13 | uses reflection to build more flexible and re-usable Catalyst components. |
14 | |
15 | The main application module (usually called C<MyApp> or C<MyApp.pm> in documentation) |
16 | looks exactly like a typical Catalyst application module. Reaction's modular architecture |
17 | allows it therefor to be integrated into other Catalyst applications, or to integrate |
18 | other Catalyst extensions and components itself. |
19 | |
20 | =head1 CONTROLLERS |
21 | |
22 | Usually in Catalyst applications the controller's actions will take their arguments, |
23 | maybe modify them or clean them up. After that they are processed by the model and then |
24 | stashed away to be later used by the view. |
25 | |
26 | Reactions approach is a bit different. The cleanup and validation of values, and the |
27 | involvement of the model are abstracted into a L<Reaction::InterfaceModel::Action> |
28 | subclass. Examples for such actions would be C<Create>, C<Update> or C<Delete> in a |
29 | CRUD situation. |
30 | |
31 | Controllers that use Reaction have to inherit from L<Reaction::UI::Controller> or a |
32 | subclass of it. Some other useful controller base classes are: |
33 | |
34 | =over |
35 | |
36 | =item * |
37 | |
38 | L<Reaction::UI::Controller::Root> should be the base for the root controller to |
39 | every chain of Reaction actions. It will provide a C<base> action you can chain |
40 | to which will make sure the L<window viewport|/VIEWPORTS> and |
41 | L<focus stack|/FOCUS STACK> are set up. |
42 | |
43 | =item * |
44 | |
45 | L<Reaction::UI::Controller::Collection> to ease the creation of components that act |
46 | on collections as their model (database results for example). It provides actions |
47 | to list and view the collection items. |
48 | |
49 | =item * |
50 | |
51 | L<Reaction::UI::Controller::Collection::CRUD> is a subclass of the above and provides |
52 | additional C<create>, C<update>, C<delete> and C<delete_all> actions. |
53 | |
54 | =back |
55 | |
56 | =head1 VIEWPORTS |
57 | |
58 | Viewports represent the components that render your page when combined. |
59 | |
60 | The C<begin> action in L<Reaction::Controller::Root> creates a new L<Reaction::UI::Window> |
61 | object and stores it as C<window> in the stash. The L<focus stack|/FOCUSSTACKS> of that |
62 | window object is used as the base focus stack for the request. |
63 | |
64 | You can add a new inner viewport to the focus stack with the C<push_viewport> method |
65 | available on your controller: |
66 | |
67 | $controller->push_viewport($viewport_class, %viewport_args); |
68 | |
69 | This will add a new instance of C<$viewport_class> to the current focus stack using |
70 | C<%viewport_args> as arguments. For more information on the usage and other options |
71 | (for example the C<next_action> option, which redirects afterwards) see |
72 | L<Reaction::UI::FocusStack> and L<Reaction::UI::ViewPort>. |
73 | |
74 | You can use the L<Reaction::UI::ViewPort::Action> viewport to build viewports |
75 | that perform typical form actions like OK, Apply and Close. |
76 | |
77 | =head1 FOCUSSTACKS |
78 | |
79 | Viewports are pushed onto the current focus stack. The C<end> action in |
80 | L<Reaction::Controller::Root> will C<flush> the L<Reaction::UI::Window> |
81 | object stored as C<window> in the stash. |
82 | |
83 | =head1 DOMAIN MODELS |
84 | |
85 | The domain models should be completely decoupled from the application and it's business |
86 | logic. Normally, you need to decide whether to put your business logic in your controller |
87 | or in your model. Reaction solves this problem by using L<interface models|/INTERFACE MODELS> |
88 | as a separation between the two. |
89 | |
90 | If you want your domain model to be reflectable (L<DBIx::Class> for example) you will have |
91 | to use L<Moose> to add attribute metadata to those classes. |
92 | |
93 | =head1 INTERFACE MODELS |
94 | |
95 | The interface models contain your business logic. That is, the application specific logic |
96 | representing the model your application will use. |
97 | |
98 | An interface model consists of action classes subclassing L<Reaction::InterfaceModel::Action>. |
99 | These instances will have both the request context and the target model available and can do |
100 | their work in a C<do_apply> method. |
101 | |
102 | To allow your own models to be tied in to reflective controllers like |
103 | L<Reaction::Controller::Collection>, you can subclass L<Reaction::InterfaceModel::Object>. |
104 | That will provide you with a way to let the viewports introspect the actions that your |
105 | interface model defines for this model. |
106 | |
107 | An example of this would be: |
108 | |
109 | - MyApp::Controller::Foo is a Reaction::Controller::Collection::CRUD |
110 | for MyApp::Model::Foo |
111 | - The model_name config setting is 'Model::Foo' |
112 | - User calls action MyApp::Controller::Foo->delete_old |
113 | - The 'delete_old' controller action will call |
114 | $self->basic_model_action($c, \%vp_args) |
115 | - The 'target' option in %vp_args will be asked for an action that |
116 | corresponds with the 'delete_old' controller action |
117 | - An instance of MyApp::Model::Foo::Action::DeleteOld is |
118 | returned |
119 | - This is passed as 'model' to a new instance of |
120 | Reaction::UI::ViewPort::Action which is then pushed |
121 | onto the focus stack. |
122 | |
123 | Form processing as provided by L<Reaction::UI::ViewPort::Action> is a very good |
124 | example of Reaction's usefulness; Instead of creating a new dialog for every |
125 | form using myriads of helper functions, you provide a controller baseclass |
126 | rendering the dialog by introspecting an interface model object with fields and |
127 | actions. |
128 | |
129 | Then you just need to create a new controller and interface model for your new |
130 | dialog and it just works. |
131 | |
132 | If your model is a L<DBIx::Class::Schema> and contains L<Moose> metadata, you |
133 | can let L<Reaction::InterfaceModel::Reflector::DBIC> set up your interface |
134 | model objects and actions. |
135 | |
136 | =head1 SKINS, LAYOUTS AND WIDGETS |
137 | |
138 | When you push a viewport onto the focus stack like this: |
139 | |
140 | $controller->push_viewport('Reaction::UI::ViewPort::SiteLayout'); |
141 | |
142 | Reaction will look for a layout file named |
143 | C<$search_path/skin/$skin_name/layout/site_layout.tt>. If it can't find it, |
144 | it will also look in the base skin and search paths. |
145 | |
146 | You can also provide a specific layout: |
147 | |
148 | $controller->push_viewport( |
149 | 'Reaction::UI::ViewPort::SiteLayout', |
150 | layout => 'my_site_layout', |
151 | ); |
152 | |
153 | A new instance of L<Reaction::UI::LayoutSet> will be created using the layout |
154 | file. It is then used to determine the class of widget to create. The widget |
155 | contains the Perl code counterpart of the templating part in the layout file. |
156 | |
157 | The widget is either determined by the C<=widget> template directive in the |
158 | layout file or by the L<Reaction::UI::Skin> object created to represent the |
159 | skin. |
160 | |
161 | The details of skins or layouts are documented in L<Reaction::Manual::Templates>. |
162 | |
163 | =head1 SEE ALSO |
164 | |
165 | =over |
166 | |
167 | =item * L<Reaction::Manual> |
168 | |
169 | =item * L<Reaction::Manual::Intro> |
170 | |
171 | =back |
172 | |
173 | =head1 AUTHORS |
174 | |
175 | See L<Reaction::Class> for authors. |
176 | |
177 | =head1 LICENSE |
178 | |
179 | See L<Reaction::Class> for the license. |
180 | |
181 | =cut |