Mercurial > pub > Impl
view Lib/IMPL/Web/Application/OperationContract.pm @ 245:7c517134c42f
Added Unsupported media type Web exception
corrected resourceLocation setting in the resource
Implemented localizable resources for text messages
fixed TT view scopings, INIT block in controls now sets globals correctly.
author | sergey |
---|---|
date | Mon, 29 Oct 2012 03:15:22 +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