From 7ff308905da567a0ac9fbebf63a04ede5696cded Mon Sep 17 00:00:00 2001 From: edenc Date: Mon, 17 Dec 2007 18:45:59 +0000 Subject: moved docs to /old --- old/Manual/Cookbook.pod | 74 ++++++++++++ old/Manual/Example.pod | 304 +++++++++++++++++++++++++++++++++++++++++++++++ old/Manual/FAQ.pod | 101 ++++++++++++++++ old/Manual/Internals.pod | 270 +++++++++++++++++++++++++++++++++++++++++ old/Manual/Intro.pod | 62 ++++++++++ 5 files changed, 811 insertions(+) create mode 100644 old/Manual/Cookbook.pod create mode 100644 old/Manual/Example.pod create mode 100644 old/Manual/FAQ.pod create mode 100644 old/Manual/Internals.pod create mode 100644 old/Manual/Intro.pod (limited to 'old/Manual') diff --git a/old/Manual/Cookbook.pod b/old/Manual/Cookbook.pod new file mode 100644 index 0000000..e04c6ee --- /dev/null +++ b/old/Manual/Cookbook.pod @@ -0,0 +1,74 @@ +=head1 NAME + +Reaction::Manual::Cookbook - Miscellaneous recipes + +=head1 RECIPES + +These should include some hopefully useful tips and tricks! + +=head2 Display + +These would typically go in your /root directory along with your other +templates. + +=head3 Alternating listview row styles with CSS + +Filename: listview + + [% + + PROCESS base/listview; + + row_block = 'listview_row_fancy'; + + BLOCK listview_row_fancy; + + IF loop.count % 2 == 1; + attrs.class = 'dark'; + ELSE; + attrs.class = 'light'; + END; + + INCLUDE listview_row; + + END; + + %] + +=head3 Displaying heading on action forms + +Filename: form_base + + [% + + PROCESS base/form_base; + + main_block = 'form_base_control_fancy'; + + BLOCK form_base_control_fancy; + + action_class = self.action.meta.name.split('::').pop; + '

'; action_class.split('(?=[A-Z])').join(' '); '

'; + INCLUDE form_base_control; + + END; + + %] + +=head2 Controllers + +Things + +=head2 Models + +Stuff + +=head1 AUTHORS + +See L for authors. + +=head1 LICENSE + +See L for the license. + +=cut diff --git a/old/Manual/Example.pod b/old/Manual/Example.pod new file mode 100644 index 0000000..02a55fe --- /dev/null +++ b/old/Manual/Example.pod @@ -0,0 +1,304 @@ +=head1 NAME + +Reaction::Manual::Example - Simple Reaction example + +=head1 DESCRIPTION + +This tutorial will guide you through the process of setting up and testing a +very basic CRUD application based on the database from +L. + +You need at least a fairly basic understanding of L for +this example to have value for you. + +=head2 Installation + +Install L via CPAN. + +Install Reaction from http://code2.0beta.co.uk/reaction/svn via SVN or SVK. + +Set up the database as mentioned in L. Don't do +any of the DBIx::Class related stuff, only the SQLite database. + +=head2 Create the application + + catalyst.pl Test::Reaction + cd Test-Reaction + script/test_reaction_create.pl Model Test::Reaction DBIC::Schema Test::Reaction::DB + +Also, remember to include Catalyst::Plugin::I18N in your plugin list, like +this: + + use Catalyst qw/-Debug ConfigLoader Static::Simple I18N/; + +=head2 Set up DBIx::Class::Schema + +In addition to the normal DBIC stuff, you need to moosify your DBIC classes. + +Change directory back from db to the directory app: + + cd lib/Test/Reaction + mkdir DB + +Then, create the following DBIx::Class::Schema classes: + +DB.pm: + + package Test::Reaction::DB; + + use base 'DBIx::Class::Schema'; + + __PACKAGE__->load_classes; + + 1; + +DB/Artist.pm: + + package Test::Reaction::DB::Artist; + + use base 'DBIx::Class'; + use Reaction::Class; + + has 'artistid' => ( isa => 'Int', is => 'ro', required => 1 ); + has 'name' => ( isa => 'NonEmptySimpleStr', is => 'rw', required => 1 ); + + sub display_name { + my $self = shift; + return $self->name; + } + + __PACKAGE__->load_components(qw/PK::Auto Core/); + __PACKAGE__->table('artist'); + __PACKAGE__->add_columns(qw/ artistid name /); + __PACKAGE__->set_primary_key('artistid'); + __PACKAGE__->has_many( 'cds' => 'Test::Reaction::DB::Cd' ); + + 1; + +DB/Cd.pm: + + package Test::Reaction::DB::Cd; + + use base 'DBIx::Class'; + use Reaction::Class; + + has 'cdid' => ( isa => 'Int', is => 'ro', required => 1 ); + has 'artist' => + ( isa => 'Test::Reaction::DB::Artist', is => 'rw', required => 1 ); + has 'title' => ( isa => 'NonEmptySimpleStr', is => 'rw', required => 1 ); + + sub display_name { + my $self = shift; + return $self->title; + } + + __PACKAGE__->load_components(qw/PK::Auto Core/); + __PACKAGE__->table('cd'); + __PACKAGE__->add_columns(qw/ cdid artist title/); + __PACKAGE__->set_primary_key('cdid'); + __PACKAGE__->belongs_to( 'artist' => 'Test::Reaction::DB::Artist' ); + __PACKAGE__->has_many( 'tracks' => 'Test::Reaction::DB::Track' ); + + 1; + +DB/Track.pm: + + package Test::Reaction::DB::Track; + + use base 'DBIx::Class'; + use Reaction::Class; + + has 'trackid' => ( isa => 'Int', is => 'ro', required => 1 ); + has 'cd' => ( isa => 'Test::Reaction::DB::Cd', is => 'rw', required => 1 ); + has 'title' => ( isa => 'NonEmptySimpleStr', is => 'rw', required => 1 ); + + __PACKAGE__->load_components(qw/PK::Auto Core/); + __PACKAGE__->table('track'); + __PACKAGE__->add_columns(qw/ trackid cd title/); + __PACKAGE__->set_primary_key('trackid'); + __PACKAGE__->belongs_to( 'cd' => 'Test::Reaction::DB::Cd' ); + + 1; + +=head3 Reaction attributes + +See L + +=head3 The rest + +Reaction will use I for displaying when there is a 1:Many or +Many:Many relation. It will return a suitable text representation. + +=head2 Models + +=head3 Create Test::Reaction::Model::Action + +Still in lib/Test/Reaction, create + +Model/Action.pm: + + package Test::Reaction::Model::Action; + + use Reaction::Class; + + use Test::Reaction::DB; + + use aliased 'Reaction::InterfaceModel::Action::DBIC::ActionReflector'; + + my $r = ActionReflector->new; + + $r->reflect_actions_for( 'Test::Reaction::DB::Artist' => __PACKAGE__ ); + $r->reflect_actions_for( 'Test::Reaction::DB::Cd' => __PACKAGE__ ); + $r->reflect_actions_for( 'Test::Reaction::DB::Track' => __PACKAGE__ ); + + 1; + +=head2 Controllers + +Reaction controllers inherit from Reaction::UI::CRUDController, like this: + +Controller/Artist.pm + + package Test::Reaction::Controller::Artist; + + use strict; + use warnings; + use base 'Reaction::UI::CRUDController'; + use Reaction::Class; + + __PACKAGE__->config( + model_base => 'Test::Reaction', + model_name => 'Artist', + action => { base => { Chained => '/base', PathPart => 'artist' } } + ); + + 1; + +Controller/Cd.pm + + package Test::Reaction::Controller::Cd; + + use strict; + use warnings; + use base 'Reaction::UI::CRUDController'; + use Reaction::Class; + + __PACKAGE__->config( + model_base => 'Test::Reaction', + model_name => 'Cd', + action => { base => { Chained => '/base', PathPart => 'cd' } } + ); + + 1; + +Controller/Track.pm + + package Test::Reaction::Controller::Track; + + use strict; + use warnings; + use base 'Reaction::UI::CRUDController'; + use Reaction::Class; + + __PACKAGE__->config( + model_base => 'Test::Reaction', + model_name => 'Track', + action => { base => { Chained => '/base', PathPart => 'track' } } + ); + + 1; + +Finally, change Controller/Root.pm to + + package Test::Reaction::Controller::Root; + + use strict; + use warnings; + use base 'Reaction::UI::RootController'; + use Reaction::Class; + + use aliased 'Reaction::UI::ViewPort'; + use aliased 'Reaction::UI::ViewPort::ListView'; + use aliased 'Reaction::UI::ViewPort::ActionForm'; + + __PACKAGE__->config->{namespace} = ''; + + sub base :Chained('/') :PathPart('') :CaptureArgs(0) { + my ($self, $c) = @_; + + $self->push_viewport(ViewPort, layout => 'xhtml'); + } + + sub root :Chained('base') :PathPart('') :Args(0) { + my ($self, $c) = @_; + + $self->push_viewport(ViewPort, layout => 'index'); + } + + 1; + +=head2 View + +View/XHTML.pm looks like this + + package Test::Reaction::View::XHTML; + + use Reaction::Class; + + extends 'Reaction::UI::Renderer::XHTML'; + + 1; + +This is all the perly stuff. Now return to the base Test-Reaction directory and +create root/index: + + [% + + main_block = 'index'; + + BLOCK index; + + %]

artist

+

cd

+

track

[% + + END; + + %] + +=head2 Running + +Now all that remains is to tell catalyst about the root and the model. Let +test_reaction.yml look like this: + + --- + name: Test::Reaction + Controller::Root: + view_name: 'XHTML' + window_title: 'Reaction Test App' + Model::Test::Reaction: + schema_class: 'Test::Reaction::DB' + connect_info: + - 'dbi:SQLite:dbname=database/example.db' + +The finals step for this example is to link to Reaction's templates: + + ln -s /root/base/ root/base + +At last you're now ready to run the server + + script/test_reaction_server.pl + +=head1 Notes + +=head1 TODO + +=head1 AUTHORS + +See L for authors. + +=head1 LICENSE + +See L for the license. + +=cut diff --git a/old/Manual/FAQ.pod b/old/Manual/FAQ.pod new file mode 100644 index 0000000..96f20fd --- /dev/null +++ b/old/Manual/FAQ.pod @@ -0,0 +1,101 @@ +=head1 NAME + +Reaction::Manual::FAQ + +=head2 INTRODUCTION + +=head3 What is Reaction? + +Reaction is an MVCish framework that is designed with two goals in mind: +"don't repeat yourself" and "components rule." + +=head3 How is it different from other MVC frameworks? + +Reaction is more flexible and abstract. Web development is only a specialized +set of what Reaction is designed to provide - the inner classes are general +enough to be used in many different environments and for solving non-web +problems. + +It is planned to go a lot further than just the web - we want to develop GUIs +and CLIs as easily and painlessly as possible, using Reaction. How about +writing your web application and instantly getting a CLI to go with it? That's +only part of the flexibility we have in mind. + +=head3 How is it different from Catalyst? + +Catalyst is MVC-based whereas Reaction splits the Model into 2 parts: The +"Domain Model" and the "Interface Model." Web development is only a sample of +what Reaction can do - but it already comes bundled with the basic components +that you would have to program in Catalyst. At the moment, Reaction runs on +Catalyst for web development. + +=head3 What's a Domain? + +A domain is the field where an abstraction makes sense. For example, to build +a web site a programmer may come up with an abstraction of a User, Products, +User roles, etc. These concepts are just one particular implementation of all +the possible abstractions for that web site -- the set of all these possible +abstractions make up the Domain. + +=head3 What's a Domain Model? + +A Domain Model is an actual computational model of an abstraction. In most +cases these models are business-based, as in the set of objects that make up +the representation for a particular domain, such as Users, Products, User +Roles, etc. + +=head3 What's an Interface Model? + +A well defined model for the common operations involved in a particular mode +of interaction with the domain. In other words, it's a layer around the Domain +Model that provides interaction with it. One example would be an authorization +procedure for different views of the same data, based on user's credentials. + +=head3 I'm lost! What does "Model" mean? + +The term "model" can mean two things: "model as in Computer Model" and "Model +as in MVC". For this document, the former will be written as just "Model" +whereas the latter will be referred to as "Model as in MVC." + +=head3 Haven't I seen these definitions elsewhere? +Yes, similar terms have been used in Java-land and Smalltalk-ville. Note that +for the sake of simplicity we are not giving rigorous (and more complex) +definitions. + +=head3 What's a View? + +=head3 What's a Viewport? + +ListView and ActionForm are subclasses of ViewPort. + +=head3 What's a Focus Stack? + +=head3 What are Tangents? + +=head3 Can I have a pony? + +=head2 USING REACTION + +=head3 Where do I put my HTML? + +Packages involved + ComponentUI + ComponentUI::Controller::Bar + ComponentUI::Controller::Baz + ComponentUI::Controller::Foo + ComponentUI::Controller::Root + ComponentUI::Model::TestDB + ComponentUI::Model::Action + ComponentUI::View::XHTML + +CRUD + +=head1 AUTHORS + +See L for authors. + +=head1 LICENSE + +See L for the license. + +=cut diff --git a/old/Manual/Internals.pod b/old/Manual/Internals.pod new file mode 100644 index 0000000..720608c --- /dev/null +++ b/old/Manual/Internals.pod @@ -0,0 +1,270 @@ +=head1 NAME + +Reaction::Manual::Internals + +=head2 Hacking on Reaction + +=head3 What is a component? + +=head3 What component types are there? + +=head3 How do I create a new component? + +=head3 How does it work with a database? + +=head3 What about Moose? + +L + +=head3 Type system + +=head3 What Perl modules should I be familiar with, in order to hack on Reaction's +internals? + +=over + +=item L + +A complete modern object system for Perl 5. + +=item L + +Use shorter package names, i.e., "X::Y::Z" as "Z". + +=item L + +The MVC application framework Reaction uses. + +=over + +=item * L + +=item * L + +=item * L + +=item * L + +=item * L + +=item * L + +=back + +=item TT + +Template Toolkit + +=item L + +Generic config file module. + +=item L + +Object/Relational mapper. + +=item L + +=item L + +=item L + +=item L + +=item L + +=item L + +=item L + +=item L + +=item L + +=item L + +=item L + +=back + +=head3 Packages involved + +=over + +=item L + +Utility class, sets up to export a few methods that return parameters for use +within Moose's C (as new parameters) in other packages. It also Cs +Moose itself. + +The methods it injects are: + +=over + +=item set_or_lazy_build($field_name) + +The attribute is required, if not provided beforehand the build_${name} method +will be called on the object when the attribute's getter is first called. If +the method does not exist, or returns undef, an error will be thrown. + +=item set_or_lazy_fail() + +The attribute is required, if not provided beforehand the 'lazy' parameter of +Moose will make it fail. + +=item trigger_adopt() + +Calls adopt_${type} after the attribute value is set to $type. + +=item register_inc_entry() + +Will mark the calling package as already included, using %INC. + +=back + +=item Reaction::InterfaceModel::Action + +=item Reaction::InterfaceModel::Action::DBIC::ResultSet::Create; + +=item Reaction::InterfaceModel::Action::DBIC::ActionReflector; + +A method "adaptor" that creates the needed objects to support CRUD DBIC +actions. In the future the code could be moved to a class higher in the +hierarchy and only contain the operations to adapt. + +Sample run: + +Reaction::InterfaceModel::Action::DBIC::ActionReflector->reflect_actions_for( +Reaction::InterfaceModel::Action::DBIC::ActionReflector=HASH(0x93cb2f0) +RTest::TestDB::Foo +ComponentUI::Model::Action +) + +Generates and evaluates: + +package ComponentUI::Model::Action::DeleteFoo; +use Reaction::Class; +extends 'Reaction::InterfaceModel::Action::DBIC::Result::Delete'; +package ComponentUI::Model::Action::UpdateFoo; +use Reaction::Class; +extends 'Reaction::InterfaceModel::Action::DBIC::Result::Update'; +has 'baz_list' => (isa => 'ArrayRef', is => 'rw', set_or_lazy_fail('baz_list'), default => sub { [] }, valid_values => sub { +$_[0]->target_model +->result_source +->related_source('links_to_baz_list') +->related_source('baz') +->resultset; +}); +has 'last_name' => (isa => 'NonEmptySimpleStr', is => 'rw', set_or_lazy_fail('last_name')); +has 'first_name' => (isa => 'NonEmptySimpleStr', is => 'rw', set_or_lazy_fail('first_name')); +package ComponentUI::Model::Action::CreateFoo; +use Reaction::Class; +extends 'Reaction::InterfaceModel::Action::DBIC::ResultSet::Create'; +has 'baz_list' => (isa => 'ArrayRef', is => 'rw', set_or_lazy_fail('baz_list'), default => sub { [] }, valid_values => sub { +$_[0]->target_model +->result_source +->related_source('links_to_baz_list') +->related_source('baz') +->resultset; +}); +has 'last_name' => (isa => 'NonEmptySimpleStr', is => 'rw', set_or_lazy_fail('last_name')); +has 'first_name' => (isa => 'NonEmptySimpleStr', is => 'rw', set_or_lazy_fail('first_name')); + +=item Reaction::InterfaceModel::Action::DBIC::Result::Delete + +=item Reaction::InterfaceModel::Action::DBIC::Result::Update + +=item Reaction::InterfaceModel::Action::DBIC::User::ResetPassword + +=item Reaction::InterfaceModel::Action::DBIC::User::Role::SetPassword + +=item Reaction::InterfaceModel::Action::DBIC::User::ChangePassword + +=item Reaction::InterfaceModel::Action::User::ResetPassword + +=item Reaction::InterfaceModel::Action::User::ChangePassword + +=item Reaction::InterfaceModel::Action::User::SetPassword + +=item Reaction::Meta::InterfaceModel::Action::ParameterAttribute + +=item Reaction::Meta::InterfaceModel::Action::Class + +=item Reaction::Types::Email + +=item Reaction::Types::Core + +=item Reaction::Types::DateTime + +=item Reaction::Types::File + +=item Reaction::Types::DBIC + +=item Reaction::UI::ViewPort::ListView + +=item Reaction::UI::ViewPort::Field::Text + +=item Reaction::UI::ViewPort::Field::ChooseMany + +=item Reaction::UI::ViewPort::Field::String + +=item Reaction::UI::ViewPort::Field::Number + +=item Reaction::UI::ViewPort::Field::HiddenArray + +=item Reaction::UI::ViewPort::Field::DateTime + +=item Reaction::UI::ViewPort::Field::File + +=item Reaction::UI::ViewPort::Field::ChooseOne + +=item Reaction::UI::ViewPort::Field::Password + +=item Reaction::UI::ViewPort::ActionForm + +=item Reaction::UI::ViewPort::Field + +=item Reaction::UI::FocusStack + +=item Reaction::UI::RootController + +=item Reaction::UI::Window + +=item Reaction::UI::Renderer::XHTML + +=item Reaction::UI::ViewPort + +=item Reaction::UI::CRUDController + +=item Reaction::UI::Controller + +=back + +=head3 Remarks about POD + +Don't use C<=over N>. POD assumes that the indent level is 4 if you leave +it out. Most POD renderers ignore your indent level anyway. + +=head2 UNSORTED + +Packages involved + +t/lib/Rtest/TestDB*: TestDB DBIC declarations. +t/lib/RTest/TestDB.pm: does DBIC populate for t/. +t/lib/RTest/UI/ XXX + +Reaction::Test::WithDB; +Reaction::Test; +Reaction::Test::Mock::Context; +Reaction::Test::Mock::Request; +Reaction::Test::Mock::Response; + +=head1 AUTHORS + +See L for authors. + +=head1 LICENSE + +See L for the license. + +=cut diff --git a/old/Manual/Intro.pod b/old/Manual/Intro.pod new file mode 100644 index 0000000..73d3846 --- /dev/null +++ b/old/Manual/Intro.pod @@ -0,0 +1,62 @@ +=head1 NAME + +Reaction::Manual::Intro - Introduction to Reaction + +=head1 INTRODUCTION + +Reaction is basically an extended MVC: + +=over + +=item Domain Model + +DBIC schema, etc. + +=item Interface Model + +Model::DBIC::Schema and Action classes. + +=item Controller + +Mediation and navigation. + +=item ViewPort + +View logic and event handling encapsulation. + +=item Renderer + +View:: classes, handed 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 Basic usage + +XXX TODO + +=head1 SEE ALSO + +=over + +=item * L + +=item * L + +=back + +=head1 AUTHORS + +See L for authors. + +=head1 LICENSE + +See L for the license. + +=cut -- cgit v1.2.3-54-g00ecf