Mercurial > pub > Impl
view Lib/IMPL/Web/Application/OperationContract.pm @ 250:129e48bb5afb
DOM refactoring
ObjectToDOM methods are virtual
QueryToDOM uses inflators
Fixed transform for the complex values in the ObjectToDOM
QueryToDOM doesn't allow to use complex values (HASHes) as values for nodes (overpost problem)
author | sergey |
---|---|
date | Wed, 07 Nov 2012 04:17:53 +0400 |
parents | 6d8092d8ce1b |
children | 4abda21186cd |
line wrap: on
line source
package IMPL::Web::Application::OperationContract; use strict; use IMPL::lang qw(:declare); use IMPL::declare { require => { Exception => 'IMPL::Exception', ArgumentException => '-IMPL::InvalidArgumentException', ResourceInterface => 'IMPL::Web::Application::ResourceInterface' }, base => [ 'IMPL::Object' => undef, 'IMPL::Object::Autofill' => '@_' ], props => [ binding => PROP_ALL, success => PROP_ALL, error => PROP_ALL ] }; sub Invoke { my ( $this, $resource, $request ) = @_; die ArgumentException->new( resource => 'A valid resource is required' ) unless eval { $resource->isa(ResourceInterface) }; my $result = eval { _InvokeDelegate($this->binding, $resource, $request) }; if (my $e = $@) { if ($this->error) { $result = _InvokeDelegate($this->error, $resource, $request, $e) ; } else { die $e; } } else { $result = _InvokeDelegate($this->success, $resource, $request, $result) if ($this->success); } return $result; } sub _InvokeDelegate { my $delegate = shift; return $delegate->(@_) if ref $delegate eq 'CODE'; return $delegate->Invoke(@_) if eval { $delegate->can('Invoke')}; } 1; __END__ =pod =head1 NAME C<IMPL::Web::Application::OperationContract> - Описание операции над веб-ресурсом. =head1 SYNOPSIS =begin code use IMPL::require { 'OperationContract' => 'IMPL::Web::Application::OperationContract', 'RedirectResponse' => 'IMPL::Web::Application::RedirectResponse' }; my $operation = OperationContract->new( binding => sub { my ($resource,$request) = @_; my $itemName = $request->param('itemName', qr/^(\w+)$/); return $model->FindItem($itemName); }, success => sub { my ($resource,$request,$result) = @_; return HttpReponse->Redirect(location => $resource->location->Child($result->id)); } ); my $response = $operation->InvokeOperation($resource); =end code =head1 DESCRIPTION Для орисания контракта операции используется понятие делегата, тоесть объекта, представляющего собой функцию, либо объект, имеющий метод C<Invoke>. Поскольку предметная область должна быть отделена от контроллеров веб-сервиса, она ничего не знает про существование ресурсов и их организацию и тем более о протоколе C<HTTP>, поэтому все вещи, связанные с формированием ответов сервера, представлениями данных и т.п. должны выполняться самими контроллерами. Поведение контроллеров описывается контрактами, в которых указываются делегаты для реализации необходимого функционала, для корректного отображения ресурсов в объекты предметной области и обратно. Контракт операции состоит из нескольких свойств, осуществляющих привязку к предметной области: =over =item * C<binding> делегат для привязки операции над ресурсом к предметной области. =item * C<success> делегат для обработки результат операции, например для формирования ответа с перенаправлением. =item * C<error> делегат для обработки исключительной ситуации, может быть использован для формирования представления для повторного ввода данных на форме. =back =head1 MEMBERS =head2 C<[get,set] binding> Привязка операции к ресурсу, например =begin code $operationContract->binding(sub { my ($resource,$action) = @_; $resource->model }) =end code Может быть как ссылка на процедуру, так и ссылкой на объект, имеющий метод C<Invoke>. =head2 C<[get,set] success> Обрабатывает результат привязки к предметной области. =begin code # redirect (for example after POST) $operationContract->success(sub { my ($resource,$action,$result) = @_; return IMPL::Web::HttpResponse ->Redirect($resource->location->Child($result->id)); }) =end code Может быть как ссылка на процедуру, так и ссылкой на объект, имеющий метод C<Invoke>. =head2 C<[get,set] error> Обрабатывает ошибку возникшую при выполнении привязки к предметной области. =begin $operationContract->error(sub { my ($resource,$action,$error) = @_; $action->form->errors->{''} = $error; return $resource->model; }); =end =cut