annotate lib/IMPL/Web/Application/Resource.pm @ 408:5c80e33f1218 ref20150831

added 'coarsen' function
author cin
date Mon, 07 Sep 2015 01:35:25 +0300
parents c6e90e02dd17
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
407
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
1 package IMPL::Web::Application::Resource;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
2 use strict;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
3
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
4 use constant {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
5 ResourceClass => __PACKAGE__
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
6 };
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
7 use Scalar::Util qw(blessed);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
8
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
9 use IMPL::lang qw(:hash :base);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
10 use IMPL::Const qw(:prop);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
11 use IMPL::declare {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
12 require => {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
13 Exception => 'IMPL::Exception',
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
14 OpException => '-IMPL::InvalidOperationException',
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
15 NotFoundException => 'IMPL::Web::NotFoundException',
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
16 ResourceInterface => '-IMPL::Web::Application',
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
17 HttpResponse => 'IMPL::Web::HttpResponse',
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
18 HttpResponseResource => 'IMPL::Web::Application::HttpResponseResource',
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
19 Loader => 'IMPL::Code::Loader'
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
20 },
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
21 base => [
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
22 'IMPL::Web::Application::ResourceBase' => '@_'
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
23 ],
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
24 props => [
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
25 access => PROP_RW,
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
26 verbs => PROP_RW,
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
27 children => PROP_RW
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
28 ]
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
29 };
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
30
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
31 __PACKAGE__->static_accessor(verbNames => [qw(get post put delete options head)]);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
32 __PACKAGE__->static_accessor(httpMethodPrefix => 'Http');
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
33
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
34 sub CTOR {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
35 my ($this, %args) = @_;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
36
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
37 my %verbs;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
38 my $httpPrefix = $this->httpMethodPrefix;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
39
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
40 foreach my $verb (@{$this->verbNames}) {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
41 my $method = exists $args{$verb} ? $args{$verb} : $this->can($httpPrefix . ucfirst($verb));
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
42 $verbs{$verb} = $method
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
43 if $method;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
44 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
45
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
46 hashApply(\%verbs,$args{verbs})
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
47 if ref($args{verbs}) eq 'HASH' ;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
48
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
49 $this->children($args{children} || $this->GetChildResources());
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
50
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
51 $this->access($args{access})
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
52 if $args{access};
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
53
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
54 $this->verbs(\%verbs);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
55 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
56
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
57 sub _isInvokable {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
58 my ($this,$method) = @_;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
59
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
60 return
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
61 (blessed($method) and $method->can('Invoke')) ||
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
62 ref($method) eq 'CODE'
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
63 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
64
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
65 sub _invoke {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
66 my ($this,$method,@args) = @_;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
67
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
68 if(blessed($method) and $method->can('Invoke')) {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
69 return $method->Invoke($this,@args);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
70 } elsif(ref($method) eq 'CODE' || (not(ref($method)) and $this->can($method))) {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
71 return $this->$method(@args);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
72 } else {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
73 die OpException->new("Can't invoke the specified method: $method");
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
74 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
75 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
76
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
77 sub HttpGet {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
78 shift->model;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
79 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
80
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
81 sub AccessCheck {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
82 my ($this,$verb) = @_;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
83
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
84 $this->_invoke($this->access,$verb)
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
85 if $this->access;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
86 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
87
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
88 sub Fetch {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
89 my ($this,$childId) = @_;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
90
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
91 my $children = $this->children
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
92 or die NotFoundException->new( $this->location->url, $childId );
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
93
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
94 if (ref($children) eq 'HASH') {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
95 if(my $child = $children->{$childId}) {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
96 return $this->_isInvokable($child) ? $this->_invoke($child, $childId) : $child;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
97 } else {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
98 die NotFoundException->new( $this->location->url, $childId );
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
99 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
100 } elsif($this->_isInvokable($children)) {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
101 return $this->_invoke($children,$childId);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
102 } else {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
103 die OpException->new("Invalid resource description", $childId, $children);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
104 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
105 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
106
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
107 sub FetchChildResource {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
108 my ($this,$childId) = @_;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
109
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
110 my $info = $this->Fetch($childId);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
111
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
112 return $info
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
113 if (is($info,ResourceInterface));
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
114
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
115 $info = {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
116 response => $info,
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
117 class => HttpResponseResource
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
118 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
119 if is($info,HttpResponse);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
120
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
121 return $this->CreateChildResource($info, $childId)
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
122 if ref($info) eq 'HASH';
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
123
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
124 die OpException->new("Invalid resource description", $childId, $info);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
125 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
126
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
127 sub CreateChildResource {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
128 my ($this,$info, $childId) = @_;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
129
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
130 my $params = hashApply(
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
131 {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
132 parent => $this,
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
133 id => $childId,
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
134 request => $this->request,
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
135 class => ResourceClass
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
136 },
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
137 $info
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
138 );
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
139
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
140 $params->{model} = $this->_invoke($params->{model})
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
141 if $this->_isInvokable($params->{model});
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
142
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
143 my $factory = Loader->default->Require($params->{class});
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
144
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
145 return $factory->new(%$params);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
146 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
147
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
148 sub GetChildResources {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
149 return {};
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
150 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
151
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
152 1;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
153
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
154 __END__
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
155
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
156 =pod
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
157
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
158 =head1 NAME
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
159
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
160 C<IMPL::Web::Application::Resource> - Ресурс C<REST> веб приложения
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
161
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
162 =head1 SYNOPSIS
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
163
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
164 =begin code
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
165
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
166 use IMPL::require {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
167 Resource => 'IMPL::Web::Application::Resource',
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
168 Security => 'IMPL::Security',
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
169 NotFoundException => 'IMPL::Web::NotFoundException',
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
170 ForbiddenException => 'IMPL::Web::ForbiddenException'
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
171 };
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
172
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
173 my $model = Resource->new(
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
174 get => sub { },
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
175 verbs => {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
176 # non-standart verbs placed here
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
177 myverb => sub { }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
178 },
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
179 #child resources can be a hash
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
180 children => {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
181 user => {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
182 # a resource class may be specified optionally
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
183 # class => Resource,
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
184 model => sub {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
185 return Security->principal
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
186 },
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
187 # the default get implementation is implied
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
188 # get => sub { shift->model },
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
189 access => sub {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
190 my ($this,$verb) = @_;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
191 die ForbiddenException->new()
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
192 if Security->principal->isNobody
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
193 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
194 },
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
195 catalog => {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
196 get => sub {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
197 my $ctx = shift->application->ConnectDb()->AutoPtr();
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
198
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
199 return $ctx->products->find_rs({ in_stock => 1 });
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
200 },
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
201 # chid resource may be created dynamically
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
202 children => sub {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
203 # binds model against the parent reource and id
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
204 my ($this,$id) = @_;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
205
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
206 ($id) = ($id =~ /^(\w+)$/)
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
207 or die NotFoundException->new($id);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
208
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
209 my $ctx = shift->application->ConnectDb()->AutoPtr();
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
210
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
211 my $item = $ctx->products->fetch($id);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
212
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
213 die NotFoundException->new()
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
214 unless $item;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
215
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
216 # return parameters for the new resource
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
217 return {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
218 model => $item,
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
219 get => sub { shift->model }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
220 };
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
221 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
222 },
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
223 # dynamically binds whole child resource. The result of binding is
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
224 # the new resource or a hash with arguments to create one
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
225 posts => sub {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
226 my ($this,$id) = @_;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
227
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
228 # this approach can be used to create a dynamic resource relaying
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
229 # on the type of the model
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
230
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
231 return Resource->new(
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
232 id => $id,
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
233 parent => $this,
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
234 get => sub { shift->model }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
235 );
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
236
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
237 # ditto
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
238 # parent and id will be mixed in automagically
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
239 # return { get => sub { shift->model} }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
240 },
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
241 post_only => {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
242 get => undef, # remove GET verb implicitly
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
243 post => sub {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
244 my ($this) = @_;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
245 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
246 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
247 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
248 );
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
249
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
250 =end code
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
251
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
252 Альтернативный вариант для создания класса ресурса.
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
253
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
254 =begin code
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
255
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
256 package MyResource;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
257
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
258 use IMPL::declare {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
259 require => {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
260 ForbiddenException => 'IMPL::Web::ForbiddenException'
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
261 },
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
262 base => [
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
263 'IMPL::Web::Application::Resource' => '@_'
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
264 ]
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
265 };
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
266
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
267 sub ds {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
268 my ($this) = @_;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
269
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
270 $this->context->{ds} ||= $this->application->ConnectDb();
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
271 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
272
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
273 sub InvokeHttpVerb {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
274 my $this = shift;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
275
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
276 $this->ds->Begin();
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
277
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
278 my $result = $this->next::method(@_);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
279
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
280 # in case of error the data context will be disposed and the transaction
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
281 # will be reverted
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
282 $this->ds->Commit();
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
283
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
284 return $result;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
285 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
286
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
287 # this method is inherited by default
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
288 # sub HttpGet {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
289 # shift->model
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
290 #
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
291 # }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
292
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
293 sub HttpPost {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
294 my ($this) = @_;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
295
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
296 my %data = map {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
297 $_,
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
298 $this->request->param($_)
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
299 } qw(name description value);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
300
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
301 die ForbiddenException->new("The item with the scpecified name can't be created'")
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
302 if(not $data{name} or $this->ds->items->find({ name => $data{name}))
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
303
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
304 $this->ds->items->insert(\%data);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
305
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
306 return $this->NoContent();
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
307 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
308
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
309 sub Fetch {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
310 my ($this,$childId) = @_;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
311
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
312 my $item = $this->ds->items->find({name => $childId})
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
313 or die NotFoundException->new();
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
314
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
315 # return parameters for the child resource
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
316 return { model => $item, role => "item food" };
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
317 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
318
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
319 =end code
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
320
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
321 =head1 MEMBERS
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
322
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
323 =head2 C<[get,set]verbs>
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
324
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
325 Хеш с C<HTTP> методами. При попытке вызова C<HTTP> метода, которого нет в этом
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
326 хеше приводит к исключению C<IMPL::Web::NotAllowedException>.
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
327
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
328 =head2 C<[get,set]access>
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
329
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
330 Метод для проверки прав доступа. Если не задан, то доспуп возможен для всех.
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
331
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
332 =head2 C<[get,set]children>
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
333
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
334 Дочерние ресурсы. Дочерние ресурсы могут быть описаны либо в виде хеша, либо
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
335 в виде метода.
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
336
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
337 =head3 C<HASH>
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
338
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
339 Данный хещ содержит в себе таблицу идентификаторов дочерних ресурсов и их
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
340 описаний.
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
341
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
342 Описание каждого ресурса представляет собой либо функцию, либо параметры для
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
343 создания ресурса C<CraeteChildResource>. Если описание в виде функции, то она
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
344 должна возвращать либо объект типа ресурс либо параметры для его создания.
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
345
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
346 =head3 C<CODE>
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
347
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
348 Если дочерние ресурсы описаны в виде функции (возможно использовать имя метода
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
349 класса текущего ресурса), то для получения дочернего ресурса будет вызвана
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
350 функция с параметрами C<($this,$childId)>, где C<$this> - текущий ресурс,
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
351 C<$childId> - идентификатор дочернего ресурса, который нужно вернуть.
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
352
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
353 Данная функция должна возвратить либо объект типа ресурс, либо ссылку на хеш с
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
354 параметрами для создания оного при помощи метода
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
355 C<CreateChildResource($params,$childId)>.
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
356
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
357 =head2 C<[virtual]Fetch($childId)>
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
358
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
359 Метод для получения дочернего ресурса.
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
360
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
361 Возвращает параметры для создания дочернего ресурса, либо уже созданный ресурс.
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
362 Создание дочернего ресурса происходит при помощи метода C<CreateChildResource()>
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
363 который добавляет недостающие параметры к возвращенным в данным методом и
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
364 создает новый ресурс
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
365
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
366 =head2 C<CreateChildResource($params,$id)>
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
367
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
368 Создает новый дочерний ресурс с указанным идентификатором и параметрами.
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
369 Автоматически заполняет параметры
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
370
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
371 =over
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
372
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
373 =item * C<parent>
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
374
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
375 =item * C<id>
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
376
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
377 =item * C<request>
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
378
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
379 =back
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
380
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
381 Тип создаваемого ресурса C<IMPL::Web::Application::Resource>, либо указывается
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
382 в параметре C<class>.
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
383
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
384 =head2 C<[virtual]HttpGet()>
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
385
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
386 Реализует C<HTTP> метод C<GET>. По-умолчанию возвращает модель.
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
387
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
388 Данный метод нужен для того, чтобы ресурс по-умолчанию поддерживал метод C<GET>,
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
389 что является самым частым случаем, если нужно изменить данное поведение, нужно:
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
390
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
391 =over
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
392
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
393 =item * Передать в параметр конструктора C<get> значение undef
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
394
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
395 =item * Переопределить метод C<HttpGet>
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
396
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
397 =item * При проверке прав доступа выдать исключение
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
398
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
399 =back
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
400
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
401 =cut
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
402