Mercurial > pub > Impl
annotate Lib/IMPL/Web/Application/ControllerUnit.pm @ 174:d920d2b70230
minor changes
| author | sergey |
|---|---|
| date | Tue, 04 Oct 2011 17:55:38 +0400 |
| parents | aaab45153411 |
| children | d1676be8afcc |
| rev | line source |
|---|---|
| 133 | 1 use strict; |
| 110 | 2 package IMPL::Web::Application::ControllerUnit; |
| 166 | 3 use parent qw(IMPL::Object); |
| 110 | 4 |
| 5 use IMPL::Class::Property; | |
| 112 | 6 use IMPL::DOM::Transform::PostToDOM; |
| 7 use IMPL::DOM::Schema; | |
| 113 | 8 use Class::Inspector; |
| 9 use File::Spec; | |
| 133 | 10 use Sub::Name; |
| 112 | 11 |
| 12 use constant { | |
| 13 CONTROLLER_METHODS => 'controller_methods', | |
| 14 STATE_CORRECT => 'correct', | |
| 15 STATE_NEW => 'new', | |
| 173 | 16 STATE_INVALID => 'invalid', |
| 17 TTYPE_FORM => 'form', | |
| 18 TTYPE_TRANS => 'tran' | |
| 112 | 19 }; |
| 110 | 20 |
| 21 BEGIN { | |
| 22 public property action => prop_get | owner_set; | |
| 23 public property application => prop_get | owner_set; | |
| 24 public property query => prop_get | owner_set; | |
|
144
b56ebc31bf18
Empty nodes no more created while transforming a post request to the DOM document
wizard
parents:
142
diff
changeset
|
25 public property response => prop_get | owner_set; |
| 111 | 26 public property formData => prop_get | owner_set; |
| 27 public property formSchema => prop_get | owner_set; | |
| 28 public property formErrors => prop_get | owner_set; | |
| 110 | 29 } |
| 30 | |
| 170 | 31 my %publicProps = map {$_->Name , 1} __PACKAGE__->get_meta(typeof IMPL::Class::PropertyInfo); |
| 133 | 32 |
| 113 | 33 __PACKAGE__->class_data(CONTROLLER_METHODS,{}); |
| 34 | |
| 170 | 35 our @schemaInc; |
| 36 | |
| 110 | 37 sub CTOR { |
| 112 | 38 my ($this,$action,$args) = @_; |
| 110 | 39 |
| 40 $this->action($action); | |
| 41 $this->application($action->application); | |
| 42 $this->query($action->query); | |
|
144
b56ebc31bf18
Empty nodes no more created while transforming a post request to the DOM document
wizard
parents:
142
diff
changeset
|
43 $this->response($action->response); |
| 112 | 44 |
| 45 $this->$_($args->{$_}) foreach qw(formData formSchema formErrors); | |
| 46 } | |
| 47 | |
| 134 | 48 sub unitNamespace() { |
| 49 "" | |
| 50 } | |
| 51 | |
| 52 sub transactions { | |
| 53 my ($self,%methods) = @_; | |
| 54 | |
| 55 while (my ($method,$info) = each %methods) { | |
| 56 if ($info and ref $info ne 'HASH') { | |
| 57 warn "Bad transaction $method description"; | |
| 58 $info = {}; | |
| 59 } | |
| 60 | |
| 61 $info->{wrapper} = 'TransactionWrapper'; | |
| 172 | 62 $info->{method} ||= $method; |
| 173 | 63 $info->{context}{transactionType} = TTYPE_TRANS; |
| 134 | 64 $self->class_data(CONTROLLER_METHODS)->{$method} = $info; |
| 65 } | |
| 66 } | |
| 67 | |
| 112 | 68 sub forms { |
| 69 my ($self,%forms) = @_; | |
| 70 | |
| 71 while ( my ($method,$info) = each %forms ) { | |
| 72 die new IMPL::Exception("A method doesn't exists in the controller",$self,$method) unless $self->can($method); | |
| 73 if ( not ref $info ) { | |
| 74 $self->class_data(CONTROLLER_METHODS)->{$method} = { | |
| 75 wrapper => 'FormWrapper', | |
| 172 | 76 schema => $info, |
| 173 | 77 method => $method, |
| 78 context => { transactionType => TTYPE_FORM } | |
| 112 | 79 }; |
| 80 } elsif (ref $info eq 'HASH') { | |
|
148
e6447ad85cb4
DOM objects now have a schema and schemaSource properties
wizard
parents:
146
diff
changeset
|
81 $info->{wrapper} = 'FormWrapper'; |
| 172 | 82 $info->{method} ||= $method; |
| 173 | 83 $info->{context}{transactionType} = TTYPE_FORM; |
|
148
e6447ad85cb4
DOM objects now have a schema and schemaSource properties
wizard
parents:
146
diff
changeset
|
84 |
|
e6447ad85cb4
DOM objects now have a schema and schemaSource properties
wizard
parents:
146
diff
changeset
|
85 $self->class_data(CONTROLLER_METHODS)->{$method} = $info; |
| 112 | 86 } else { |
| 87 die new IMPL::Exception("Unsupported method information",$self,$method); | |
| 88 } | |
| 89 } | |
| 90 } | |
| 91 | |
| 110 | 92 sub InvokeAction { |
| 93 my ($self,$method,$action) = @_; | |
| 94 | |
| 112 | 95 if (my $methodInfo = $self->class_data(CONTROLLER_METHODS)->{$method}) { |
| 173 | 96 if (my $ctx = $methodInfo->{context}) { |
| 97 $action->context->{$_} = $ctx->{$_} foreach keys %$ctx; | |
| 98 } | |
| 112 | 99 if (my $wrapper = $methodInfo->{wrapper}) { |
| 100 return $self->$wrapper($method,$action,$methodInfo); | |
| 101 } else { | |
| 102 return $self->TransactionWrapper($method,$action,$methodInfo); | |
| 103 } | |
| 110 | 104 } else { |
| 105 die new IMPL::InvalidOperationException("Invalid method call",$self,$method); | |
| 106 } | |
| 111 | 107 } |
| 108 | |
| 133 | 109 sub MakeParams { |
| 110 my ($this,$methodInfo) = @_; | |
| 111 | |
| 112 my $params; | |
| 113 if ($params = $methodInfo->{parameters} and ref $params eq 'ARRAY') { | |
| 146 | 114 return map $this->ResolveParam($_,$methodInfo->{inflate}{$_}), @$params; |
| 133 | 115 } |
| 116 return(); | |
| 117 } | |
| 118 | |
| 119 sub ResolveParam { | |
| 146 | 120 my ($this,$param,$inflate) = @_; |
| 133 | 121 |
| 122 if ( $param =~ /^::(\w+)$/ and $publicProps{$1}) { | |
| 123 return $this->$1(); | |
| 124 } else { | |
| 146 | 125 my $value; |
| 126 if ( my $rx = $inflate->{rx} ) { | |
| 127 $value = $this->action->param($param,$rx); | |
| 128 } else { | |
| 129 $value = $this->query->param($param); | |
| 130 } | |
| 131 | |
| 132 if (my $method = $inflate->{method}) { | |
| 133 $value = $this->$method($value); | |
| 134 } | |
| 135 return $value; | |
| 133 | 136 } |
| 137 } | |
| 138 | |
| 112 | 139 sub TransactionWrapper { |
| 140 my ($self,$method,$action,$methodInfo) = @_; | |
| 141 | |
| 142 my $unit = $self->new($action); | |
| 172 | 143 my $handler = $methodInfo->{method}; |
| 144 return $unit->$handler($unit->MakeParams($methodInfo)); | |
| 112 | 145 } |
| 146 | |
| 147 sub FormWrapper { | |
| 113 | 148 my ($self,$method,$action,$methodInfo) = @_; |
| 149 | |
|
171
59e5fcb59d86
Рсправления, изменена концепция веб-форм
sourcer
parents:
170
diff
changeset
|
150 my $schema = $methodInfo->{schema} ? $self->loadSchema($methodInfo->{schema}) : $self->unitSchema; |
| 113 | 151 |
| 152 my $process = $action->query->param('process') || 0; | |
| 153 my $form = $methodInfo->{form} | |
| 154 || $action->query->param('form') | |
|
171
59e5fcb59d86
Рсправления, изменена концепция веб-форм
sourcer
parents:
170
diff
changeset
|
155 || $method; |
| 112 | 156 |
| 113 | 157 my %result; |
| 112 | 158 |
| 113 | 159 my $transform = IMPL::DOM::Transform::PostToDOM->new( |
| 160 undef, | |
| 161 $schema, | |
| 162 $form | |
| 163 ); | |
| 164 | |
| 172 | 165 my $handler = $methodInfo->{method}; |
| 166 | |
| 138 | 167 $result{formName} = $form; |
| 113 | 168 $result{formSchema} = $schema; |
| 112 | 169 |
| 113 | 170 if ($process) { |
|
171
59e5fcb59d86
Рсправления, изменена концепция веб-форм
sourcer
parents:
170
diff
changeset
|
171 $result{formData} = $transform->Transform($action->query); |
| 113 | 172 $result{formErrors} = $transform->Errors->as_list; |
| 173 if ($transform->Errors->Count) { | |
| 174 $result{state} = STATE_INVALID; | |
| 175 } else { | |
| 176 $result{state} = STATE_CORRECT; | |
| 177 my $unit = $self->new($action,\%result); | |
|
127
0dce0470a3d8
In the IMPL::Web::ControllerUnit added the ability to notify a form about a wrong data from a transaction
wizard
parents:
126
diff
changeset
|
178 |
|
0dce0470a3d8
In the IMPL::Web::ControllerUnit added the ability to notify a form about a wrong data from a transaction
wizard
parents:
126
diff
changeset
|
179 eval { |
| 172 | 180 $result{result} = $unit->$handler($unit->MakeParams($methodInfo)); |
|
127
0dce0470a3d8
In the IMPL::Web::ControllerUnit added the ability to notify a form about a wrong data from a transaction
wizard
parents:
126
diff
changeset
|
181 }; |
|
0dce0470a3d8
In the IMPL::Web::ControllerUnit added the ability to notify a form about a wrong data from a transaction
wizard
parents:
126
diff
changeset
|
182 if (my $err = $@) { |
|
0dce0470a3d8
In the IMPL::Web::ControllerUnit added the ability to notify a form about a wrong data from a transaction
wizard
parents:
126
diff
changeset
|
183 $result{state} = STATE_INVALID; |
|
0dce0470a3d8
In the IMPL::Web::ControllerUnit added the ability to notify a form about a wrong data from a transaction
wizard
parents:
126
diff
changeset
|
184 if (eval { $err->isa(typeof IMPL::WrongDataException) } ) { |
|
0dce0470a3d8
In the IMPL::Web::ControllerUnit added the ability to notify a form about a wrong data from a transaction
wizard
parents:
126
diff
changeset
|
185 $result{formErrors} = $err->Args; |
|
0dce0470a3d8
In the IMPL::Web::ControllerUnit added the ability to notify a form about a wrong data from a transaction
wizard
parents:
126
diff
changeset
|
186 } else { |
|
0dce0470a3d8
In the IMPL::Web::ControllerUnit added the ability to notify a form about a wrong data from a transaction
wizard
parents:
126
diff
changeset
|
187 die $err; |
|
0dce0470a3d8
In the IMPL::Web::ControllerUnit added the ability to notify a form about a wrong data from a transaction
wizard
parents:
126
diff
changeset
|
188 } |
|
0dce0470a3d8
In the IMPL::Web::ControllerUnit added the ability to notify a form about a wrong data from a transaction
wizard
parents:
126
diff
changeset
|
189 } |
| 113 | 190 } |
| 191 } else { | |
|
171
59e5fcb59d86
Рсправления, изменена концепция веб-форм
sourcer
parents:
170
diff
changeset
|
192 if (my $initMethod = $methodInfo->{init}) { |
|
59e5fcb59d86
Рсправления, изменена концепция веб-форм
sourcer
parents:
170
diff
changeset
|
193 my $unit = $self->new($action,\%result); |
|
59e5fcb59d86
Рсправления, изменена концепция веб-форм
sourcer
parents:
170
diff
changeset
|
194 $result{formData} = $transform->Transform( $unit->$initMethod($unit->MakeParams($methodInfo)) ); |
|
59e5fcb59d86
Рсправления, изменена концепция веб-форм
sourcer
parents:
170
diff
changeset
|
195 } else { |
|
59e5fcb59d86
Рсправления, изменена концепция веб-форм
sourcer
parents:
170
diff
changeset
|
196 $result{formData} = $transform->Transform($action->query); |
|
59e5fcb59d86
Рсправления, изменена концепция веб-форм
sourcer
parents:
170
diff
changeset
|
197 } |
|
59e5fcb59d86
Рсправления, изменена концепция веб-форм
sourcer
parents:
170
diff
changeset
|
198 |
| 172 | 199 # ignore errors for new forms |
| 200 #$result{formErrors} = $transform->Errors->as_list; | |
| 113 | 201 $result{state} = STATE_NEW; |
| 202 } | |
| 112 | 203 |
| 113 | 204 return \%result; |
| 205 } | |
| 206 | |
| 207 sub loadSchema { | |
| 208 my ($self,$name) = @_; | |
| 170 | 209 |
| 210 foreach my $path (map File::Spec->catfile($_,$name) ,@schemaInc) { | |
| 211 return IMPL::DOM::Schema->LoadSchema($path) if -f $path; | |
| 212 } | |
| 113 | 213 |
| 170 | 214 die new IMPL::Exception("A schema isn't found", $name); |
| 215 } | |
| 216 | |
| 217 sub unitSchema { | |
| 218 my ($self) = @_; | |
| 219 | |
| 220 my $class = ref $self || $self; | |
| 221 | |
| 222 my @parts = split(/:+/, $class); | |
| 223 | |
| 224 my $file = pop @parts; | |
| 225 $file = "${file}.schema.xml"; | |
| 226 | |
| 227 foreach my $inc ( @schemaInc ) { | |
| 228 my $path = File::Spec->catfile($inc,@parts,$file); | |
| 126 | 229 |
| 170 | 230 return IMPL::DOM::Schema->LoadSchema($path) if -f $path; |
| 126 | 231 } |
| 170 | 232 |
| 233 return undef; | |
| 112 | 234 } |
| 235 | |
| 134 | 236 sub discover { |
| 237 my ($this) = @_; | |
| 238 | |
| 239 my $methods = $this->class_data(CONTROLLER_METHODS); | |
| 240 | |
| 241 my $namespace = $this->unitNamespace; | |
| 242 (my $module = typeof $this) =~ s/^$namespace//; | |
| 133 | 243 |
| 134 | 244 my %smd = ( |
| 245 module => [grep $_, split /::/, $module ], | |
| 246 ); | |
| 133 | 247 |
| 134 | 248 while (my ($method,$info) = each %$methods) { |
| 249 my %methodInfo = ( | |
| 250 name => $method | |
| 251 ); | |
| 160 | 252 $methodInfo{parameters} = [ grep /^[^\:]/, @{ $info->{parameters} } ] if ref $info->{parameters} eq 'ARRAY'; |
| 134 | 253 push @{$smd{methods}},\%methodInfo; |
| 254 } | |
| 255 return \%smd; | |
| 133 | 256 } |
| 257 | |
| 134 | 258 __PACKAGE__->transactions( |
| 259 discover => undef | |
| 260 ); | |
| 133 | 261 |
| 111 | 262 1; |
| 263 | |
| 264 __END__ | |
| 265 | |
| 266 =pod | |
| 267 | |
| 268 =head1 NAME | |
| 269 | |
| 270 C<IMPL::Web::Application::ControllerUnit> - базовый класс для обработчика транзакций в модели контроллера. | |
| 271 | |
| 272 =head1 DESCRIPTION | |
| 273 | |
| 113 | 274 Классы, наследуемые от данного класса называется пакетом транзакций. Часть методов в таком классе |
| 275 объявляются как транзакции при помощи методов C<transaction>, C<form>. | |
| 111 | 276 |
| 277 Перед выполнением транзакции создается экземпляр объекта, в рамках которого будет выполнена транзакция. | |
| 278 Для этого вызывается метод C<InvokeAction($method,$action)>, который создает/восстанавливает контекст | |
| 279 транзакции. | |
| 280 | |
|
128
08753833173d
Fixed a error handling issue in JSON output: errors are correctly transfered
wizard
parents:
127
diff
changeset
|
281 Транзакции на данный момент делятся на простые и формы. Различные типы транзакций выполняются при помощи |
|
08753833173d
Fixed a error handling issue in JSON output: errors are correctly transfered
wizard
parents:
127
diff
changeset
|
282 различных оберток (C<TransactionWrapper> и C<FormWrapper>). Каждая обертка отвечает за конструирование |
|
08753833173d
Fixed a error handling issue in JSON output: errors are correctly transfered
wizard
parents:
127
diff
changeset
|
283 экземпляра объекта и вызов метода для выполнения транзакции, а также за возврат результата выполнения. |
| 111 | 284 |
| 285 =head2 Простые транзакции | |
| 286 | |
| 287 Простые транзакции получаю только запрос, без предварительной обработки, и возвращенный результат напрямую | |
| 288 передается пользователю. | |
| 289 | |
| 290 =head2 Формы | |
| 291 | |
| 292 При использовании форм запрос предварительно обрабатывается, для получения DOM документа с данными формы. | |
| 293 Для постороенния DOM документа используется схема. При этом становятся доступны дополнительные свойства | |
| 294 C<formData>, C<formSchema>, C<formErrors>. | |
| 295 | |
|
128
08753833173d
Fixed a error handling issue in JSON output: errors are correctly transfered
wizard
parents:
127
diff
changeset
|
296 Результат выполнения транзакции не возвращается наверх напрямую, а включается в структуру, которая |
| 111 | 297 выглядит следующим образом |
| 298 | |
| 299 =begin code | |
| 300 | |
| 301 { | |
| 302 state => '{ new | correct | invalid }', | |
| 303 result => $transactionResult, | |
| 304 formData => $formDOM, | |
| 305 formSchema => $formSchema, | |
| 306 formErrors => @errors | |
| 307 } | |
| 308 | |
| 309 =end code | |
| 310 | |
| 311 =over | |
| 312 | |
| 313 =item C<state> | |
| 314 | |
| 315 Состояние верификации формы. | |
| 316 | |
| 317 =over | |
| 318 | |
| 319 =item C<new> | |
| 320 | |
| 321 Первоначальное содержимое формы, оно может быть некорректным, но это нормально. | |
| 322 В данном состоянии транзакция обычно не выполняется. | |
| 323 | |
| 324 =item C<correct> | |
| 325 | |
| 326 Данные формы корректны, транзакция выполнена, и ее результат доступен через поле C<result> | |
| 327 | |
| 328 =item C<invalid> | |
| 329 | |
| 330 Содержимое формы не прошло верификацию, ошибки доступны через поле C<formErrors>. Транзакция | |
| 331 не выполнялась. | |
| 332 | |
| 333 =back | |
| 334 | |
| 335 =item C<result> | |
| 336 | |
| 337 Результат выполнения транзакции, если конечно таковая выполнялась. | |
| 338 | |
| 339 =item C<formData> | |
| 340 | |
| 341 ДОМ документ с данными формами. Документ существует всегда, не зависимо от его корректности, | |
| 342 может быть использован для построения формы, уже заполненную параметрами. | |
| 343 | |
| 344 =item C<formSchema> | |
| 345 | |
| 346 Схема данных формы, может использоваться для построения динамических форм. | |
| 347 | |
| 348 =item C<formErrors> | |
| 349 | |
|
128
08753833173d
Fixed a error handling issue in JSON output: errors are correctly transfered
wizard
parents:
127
diff
changeset
|
350 Ссылка на массив с ошибками при проверки формы. |
| 111 | 351 |
| 352 =back | |
| 353 | |
| 354 =head1 MEMBERS | |
| 355 | |
| 356 =over | |
| 357 | |
| 358 =item C<[get] application> | |
| 359 | |
|
128
08753833173d
Fixed a error handling issue in JSON output: errors are correctly transfered
wizard
parents:
127
diff
changeset
|
360 Объект приложения, которое обрабатывает запрос. |
|
08753833173d
Fixed a error handling issue in JSON output: errors are correctly transfered
wizard
parents:
127
diff
changeset
|
361 |
| 111 | 362 =item C<[get] query> |
| 363 | |
|
128
08753833173d
Fixed a error handling issue in JSON output: errors are correctly transfered
wizard
parents:
127
diff
changeset
|
364 Текущий запрос. |
|
08753833173d
Fixed a error handling issue in JSON output: errors are correctly transfered
wizard
parents:
127
diff
changeset
|
365 |
| 111 | 366 =item C<[get] response> |
| 367 | |
|
128
08753833173d
Fixed a error handling issue in JSON output: errors are correctly transfered
wizard
parents:
127
diff
changeset
|
368 Текущий ответ. |
|
08753833173d
Fixed a error handling issue in JSON output: errors are correctly transfered
wizard
parents:
127
diff
changeset
|
369 |
| 111 | 370 =item C<[get] formData> |
| 371 | |
|
128
08753833173d
Fixed a error handling issue in JSON output: errors are correctly transfered
wizard
parents:
127
diff
changeset
|
372 C<IMPL::DOM::Document> документ с данныим, если данный запрос является формой. |
|
08753833173d
Fixed a error handling issue in JSON output: errors are correctly transfered
wizard
parents:
127
diff
changeset
|
373 |
| 111 | 374 =item C<[get] formSchema> |
| 375 | |
|
128
08753833173d
Fixed a error handling issue in JSON output: errors are correctly transfered
wizard
parents:
127
diff
changeset
|
376 C<IMPL::DOM::Schema> документ со схемой формы данного запроса. |
|
08753833173d
Fixed a error handling issue in JSON output: errors are correctly transfered
wizard
parents:
127
diff
changeset
|
377 |
| 111 | 378 =item C<[get] formErrors> |
| 379 | |
|
128
08753833173d
Fixed a error handling issue in JSON output: errors are correctly transfered
wizard
parents:
127
diff
changeset
|
380 Ошибки верификации данных, если таковые были. Обычно при наличии ошибок в форме, транзакция |
|
08753833173d
Fixed a error handling issue in JSON output: errors are correctly transfered
wizard
parents:
127
diff
changeset
|
381 не выполняется, а эти ошибки передаются в ответ. |
|
08753833173d
Fixed a error handling issue in JSON output: errors are correctly transfered
wizard
parents:
127
diff
changeset
|
382 |
| 111 | 383 =item C<InvokeAction($method,$action)> |
| 384 | |
| 385 Конструирует контекст выполнения транзакции, может быть переопределен для конструирования контекста по | |
| 112 | 386 своим правилам. |
| 387 | |
| 388 =item C<TransactionWrapper($method,$action,$methodInfo)> | |
| 389 | |
| 390 Обертка для конструирования простых транзакций, может быть переопределен для конструирования контекста по | |
| 391 своим правилам. | |
| 392 | |
| 393 =item C<FormWrapper($method,$action,$methodInfo)> | |
| 394 | |
| 395 Обертка для конструирования форм, может быть переопределен для конструирования контекста по | |
| 396 своим правилам. | |
| 111 | 397 |
| 134 | 398 =item C<discover()> |
| 399 | |
| 400 Метод, опубликованный для вызова контроллером, возвращает описание методов в формате C<Simple Module Definition>. | |
| 401 | |
| 402 =begin code | |
| 403 | |
| 404 # SMD structure | |
| 405 { | |
| 406 module => ['Foo','Bar'], | |
| 407 methods => [ | |
| 408 { | |
| 409 name => 'search', | |
| 410 parameters => ['text','limit'] #optional | |
| 411 } | |
| 412 ] | |
| 413 } | |
| 414 | |
| 415 =end code | |
| 416 | |
| 111 | 417 =back |
| 418 | |
| 419 =head1 EXAMPLE | |
| 420 | |
| 421 =begin code | |
| 422 | |
| 423 package MyBooksUnit; | |
| 424 use strict; | |
| 166 | 425 use parent qw(IMPL::Web::Application::ControllerUnit); |
| 111 | 426 |
| 427 __PACKAGE__->PassThroughArgs; | |
| 428 | |
| 134 | 429 sub unitDataClass { 'My::Books' } |
| 430 | |
| 431 __PACKAGE__->transactions( | |
| 432 find => { | |
| 433 parameters => [qw(author)] | |
| 434 }, | |
| 435 info => { | |
| 436 parameters => [qw(id)] | |
| 437 } | |
| 438 ); | |
| 111 | 439 __PACKAGE__->forms( |
| 440 create => 'books.create.xml' | |
| 441 ); | |
| 442 | |
| 443 sub find { | |
| 134 | 444 my ($this,$author) = @_; |
| 111 | 445 |
| 134 | 446 return $this->ds->find({author => $author}); |
| 111 | 447 } |
| 448 | |
| 449 sub info { | |
| 134 | 450 my ($this,$id) = @_; |
| 111 | 451 |
| 134 | 452 return $this->ds->find({id => $id}); |
| 111 | 453 } |
| 454 | |
| 455 sub create { | |
| 456 my ($this) = @_; | |
| 457 | |
| 458 my %book = map { | |
| 134 | 459 $_->nodeName, $_->nodeValue |
| 460 } $this->formData->selectNodes([qw(author_id title year ISBN)]); | |
| 111 | 461 |
| 134 | 462 return $this->ds->create(\%book); |
| 111 | 463 } |
| 464 | |
| 465 =end code | |
| 466 | |
| 467 =cut |
