=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<Moose>
=head3 Type system
=head3 What Perl modules should I be familiar with, in order to hack on Reaction's
internals?
=over
=item L<Moose>
A complete modern object system for Perl 5.
=item L<aliased>
Use shorter package names, i.e., "X::Y::Z" as "Z".
=item L<Catalyst>
The MVC application framework Reaction uses.
=over
=item * L<Catalyst::Controller::BindLex>
=item * L<Catalyst::Model::DBIC::Schema>
=item * L<Catalyst::Plugin::ConfigLoader>
=item * L<Catalyst::Plugin::I18N>
=item * L<Catalyst::Plugin::Static::Simple>
=item * L<Catalyst::View::TT>
=back
=item TT
Template Toolkit
=item L<Config::General>
Generic config file module.
=item L<DBIx::Class>
Object/Relational mapper.
=item L<DateTime>
=item L<DateTime::Format::MySQL>
=item L<Digest::MD5>
=item L<Email::MIME>
=item L<Email::MIME::Creator>
=item L<Email::Send>
=item L<Email::Valid>
=item L<SQL::Translator>
=item L<Test::Class>
=item L<Test::Memory::Cycle>
=item L<Time::ParseDate>
=back
=head3 Packages involved
=over
=item L<Reaction::Class>
Utility class, sets up to export a few methods that return parameters for use
within Moose's C<has> (as new parameters) in other packages. It also C<use>s
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<Reaction::Class> for authors.
=head1 LICENSE
See L<Reaction::Class> for the license.
=cut