DBIx-Class-0.07006 >
0.08127
との差分
DBIx::Class::Manual::Cookbook 0.08127 と 0.07006 の差分
1 | =encoding utf8 | |
2 | 1 | |
2 | =encoding euc-jp | |
3 | ||
3 | 4 | =head1 名前 |
4 | 5 | |
5 | 6 | DBIx::Class::Manual::Cookbook - レシピいろいろ |
6 | 7 | |
7 | =head1 | |
8 | =head1 レシピ | |
8 | 9 | |
9 | =head2 | |
10 | =head2 検索 | |
10 | 11 | |
11 | = | |
12 | =head3 ページ処理された結果セット | |
12 | 13 | |
13 | 14 | When you expect a large number of results, you can ask L<DBIx::Class> for a |
14 | paged resultset, which will fetch only a | |
15 | paged resultset, which will fetch only a small number of records at a time: | |
15 | 16 | |
16 | =end original | |
17 | ||
18 | 17 | 結果セットが膨大になりそうなら、ページ処理された結果をL<DBIx::Class>で取得できます。 |
19 | 一回に、 | |
18 | 一回に、少しのレコードしかとってきません: | |
20 | 19 | |
21 | 20 | my $rs = $schema->resultset('Artist')->search( |
22 | 21 | undef, |
23 | 22 | { |
24 | 23 | page => 1, # page to return (defaults to 1) |
25 | 24 | rows => 10, # number of results per page |
26 | 25 | }, |
27 | 26 | ); |
28 | 27 | |
29 | 28 | return $rs->all(); # all records for page 1 |
30 | 29 | |
31 | | |
30 | The C<page> attribute does not have to be specified in your search: | |
32 | 31 | |
33 | ||
32 | C<page>属性は検索に指定する必要はありません: | |
34 | 33 | |
35 | ||
34 | my $rs = $schema->resultset('Artist')->search( | |
36 | ||
35 | undef, | |
36 | { | |
37 | rows => 10, | |
38 | } | |
39 | ); | |
37 | 40 | |
38 | ||
41 | return $rs->page(1); # DBIx::Class::ResultSet containing first 10 records | |
39 | 42 | |
43 | In either of the above cases, you can return a L<Data::Page> object for the | |
44 | resultset (suitable for use in e.g. a template) using the C<pager> method: | |
45 | ||
40 | 46 | 上のケースのいずれでも、結果セットに、L<Data::Page>オブジェクト(テンプレートに使うのに適した) |
41 | 47 | を得ることができます。C<pager>メソッドを使って: |
42 | 48 | |
43 | 49 | return $rs->pager(); |
44 | 50 | |
45 | =head | |
51 | =head3 複雑な WHERE節 | |
46 | 52 | |
47 | =begin original | |
48 | ||
49 | 53 | Sometimes you need to formulate a query using specific operators: |
50 | 54 | |
51 | =end original | |
52 | ||
53 | 55 | 特定の演算子を使ったクエリを定式化する必要がある時もあるでしょう: |
54 | 56 | |
55 | 57 | my @albums = $schema->resultset('Album')->search({ |
56 | 58 | artist => { 'like', '%Lamb%' }, |
57 | 59 | title => { 'like', '%Fear of Fours%' }, |
58 | 60 | }); |
59 | 61 | |
60 | =begin original | |
61 | ||
62 | 62 | This results in something like the following C<WHERE> clause: |
63 | 63 | |
64 | =end original | |
65 | ||
66 | 64 | 結果は下記のC<WHERE>節のようなものになります: |
67 | 65 | |
68 | WHERE artist LIKE | |
66 | WHERE artist LIKE '%Lamb%' AND title LIKE '%Fear of Fours%' | |
69 | 67 | |
70 | =begin original | |
71 | ||
72 | And the following bind values for the placeholders: C<'%Lamb%'>, C<'%Fear of | |
73 | Fours%'>. | |
74 | ||
75 | =end original | |
76 | ||
77 | そして、プレースフォルダーのために、バインドする値を続けます: C<%Lamb%>, C<'%Fear of | |
78 | Fours%'>. | |
79 | ||
80 | =begin original | |
81 | ||
82 | 68 | Other queries might require slightly more complex logic: |
83 | 69 | |
84 | =end original | |
85 | ||
86 | 70 | もうちょっと複雑なロジックが必要な他のクエリもあるでしょう: |
87 | 71 | |
88 | 72 | my @albums = $schema->resultset('Album')->search({ |
89 | 73 | -or => [ |
90 | 74 | -and => [ |
91 | 75 | artist => { 'like', '%Smashing Pumpkins%' }, |
92 | 76 | title => 'Siamese Dream', |
93 | 77 | ], |
94 | 78 | artist => 'Starchildren', |
95 | 79 | ], |
96 | 80 | }); |
97 | 81 | |
98 | =begin original | |
99 | ||
100 | 82 | This results in the following C<WHERE> clause: |
101 | 83 | |
102 | =end original | |
103 | ||
104 | 84 | 結果は下記のC<WHERE>節になります: |
105 | 85 | |
106 | 86 | WHERE ( artist LIKE '%Smashing Pumpkins%' AND title = 'Siamese Dream' ) |
107 | 87 | OR artist = 'Starchildren' |
108 | 88 | |
109 | =begin original | |
110 | ||
111 | 89 | For more information on generating complex queries, see |
112 | 90 | L<SQL::Abstract/WHERE CLAUSES>. |
113 | 91 | |
114 | =end original | |
115 | ||
116 | 92 | 複雑なクエリをつくるためのより詳しい説明は、L<SQL::Abstract/WHERE CLAUSES>を見てください。 |
117 | 93 | |
118 | =head | |
94 | =head3 特定のカラムを使う | |
119 | 95 | |
120 | Sometimes you need only the first "top" row of a resultset. While this | |
121 | can be easily done with L<< $rs->first|DBIx::Class::ResultSet/first | |
122 | >>, it is suboptimal, as a full blown cursor for the resultset will be | |
123 | created and then immediately destroyed after fetching the first row | |
124 | object. L<< $rs->single|DBIx::Class::ResultSet/single >> is designed | |
125 | specifically for this case - it will grab the first returned result | |
126 | without even instantiating a cursor. | |
127 | ||
128 | Before replacing all your calls to C<first()> with C<single()> please observe the | |
129 | following CAVEATS: | |
130 | ||
131 | =over | |
132 | ||
133 | =item * | |
134 | ||
135 | While single() takes a search condition just like search() does, it does | |
136 | _not_ accept search attributes. However one can always chain a single() to | |
137 | a search(): | |
138 | ||
139 | my $top_cd = $cd_rs->search({}, { order_by => 'rating' })->single; | |
140 | ||
141 | ||
142 | =item * | |
143 | ||
144 | Since single() is the engine behind find(), it is designed to fetch a | |
145 | single row per database query. Thus a warning will be issued when the | |
146 | underlying SELECT returns more than one row. Sometimes however this usage | |
147 | is valid: i.e. we have an arbitrary number of cd's but only one of them is | |
148 | at the top of the charts at any given time. If you know what you are doing, | |
149 | you can silence the warning by explicitly limiting the resultset size: | |
150 | ||
151 | my $top_cd = $cd_rs->search ({}, { order_by => 'rating', rows => 1 })->single; | |
152 | ||
153 | =back | |
154 | ||
155 | =head2 Arbitrary SQL through a custom ResultSource | |
156 | ||
157 | Sometimes you have to run arbitrary SQL because your query is too complex | |
158 | (e.g. it contains Unions, Sub-Selects, Stored Procedures, etc.) or has to | |
159 | be optimized for your database in a special way, but you still want to | |
160 | get the results as a L<DBIx::Class::ResultSet>. | |
161 | ||
162 | This is accomplished by defining a | |
163 | L<ResultSource::View|DBIx::Class::ResultSource::View> for your query, | |
164 | almost like you would define a regular ResultSource. | |
165 | ||
166 | package My::Schema::Result::UserFriendsComplex; | |
167 | use strict; | |
168 | use warnings; | |
169 | use base qw/DBIx::Class::Core/; | |
170 | ||
171 | __PACKAGE__->table_class('DBIx::Class::ResultSource::View'); | |
172 | ||
173 | # ->table, ->add_columns, etc. | |
174 | ||
175 | # do not attempt to deploy() this view | |
176 | __PACKAGE__->result_source_instance->is_virtual(1); | |
177 | ||
178 | __PACKAGE__->result_source_instance->view_definition(q[ | |
179 | SELECT u.* FROM user u | |
180 | INNER JOIN user_friends f ON u.id = f.user_id | |
181 | WHERE f.friend_user_id = ? | |
182 | UNION | |
183 | SELECT u.* FROM user u | |
184 | INNER JOIN user_friends f ON u.id = f.friend_user_id | |
185 | WHERE f.user_id = ? | |
186 | ]); | |
187 | ||
188 | Next, you can execute your complex query using bind parameters like this: | |
189 | ||
190 | my $friends = $schema->resultset( 'UserFriendsComplex' )->search( {}, | |
191 | { | |
192 | bind => [ 12345, 12345 ] | |
193 | } | |
194 | ); | |
195 | ||
196 | ... and you'll get back a perfect L<DBIx::Class::ResultSet> (except, of course, | |
197 | that you cannot modify the rows it contains, e.g. cannot call L</update>, | |
198 | L</delete>, ... on it). | |
199 | ||
200 | Note that you cannot have bind parameters unless is_virtual is set to true. | |
201 | ||
202 | =over | |
203 | ||
204 | =item * NOTE | |
205 | ||
206 | If you're using the old deprecated C<< $rsrc_instance->name(\'( SELECT ...') >> | |
207 | method for custom SQL execution, you are highly encouraged to update your code | |
208 | to use a virtual view as above. If you do not want to change your code, and just | |
209 | want to suppress the deprecation warning when you call | |
210 | L<DBIx::Class::Schema/deploy>, add this line to your source definition, so that | |
211 | C<deploy> will exclude this "table": | |
212 | ||
213 | sub sqlt_deploy_hook { $_[1]->schema->drop_table ($_[1]) } | |
214 | ||
215 | =back | |
216 | ||
217 | =head2 特定のカラムを使う | |
218 | ||
219 | =begin original | |
220 | ||
221 | 96 | When you only want specific columns from a table, you can use |
222 | 97 | C<columns> to specify which ones you need. This is useful to avoid |
223 | 98 | loading columns with large amounts of data that you aren't about to |
224 | 99 | use anyway: |
225 | 100 | |
226 | =end original | |
227 | ||
228 | 101 | テーブルから特定のカラムが欲しいだけのときには、C<columns>を使って、 |
229 | 102 | 必要なものを指定できます。何にも使わない大量のデータを取り込むのを |
230 | 103 | 避けることができます。 |
231 | 104 | |
232 | 105 | my $rs = $schema->resultset('Artist')->search( |
233 | 106 | undef, |
234 | 107 | { |
235 | 108 | columns => [qw/ name /] |
236 | 109 | } |
237 | 110 | ); |
238 | 111 | |
239 | 112 | # Equivalent SQL: |
240 | 113 | # SELECT artist.name FROM artist |
241 | 114 | |
242 | =begin original | |
243 | ||
244 | 115 | This is a shortcut for C<select> and C<as>, see below. C<columns> |
245 | 116 | cannot be used together with C<select> and C<as>. |
246 | 117 | |
247 | =end original | |
248 | ||
249 | 118 | 後でも見ますが、これは、C<select>とC<as>のショートカットです。 |
250 | 119 | C<columns>はC<select>とC<as>と一緒には使えません。 |
251 | 120 | |
252 | =head | |
121 | =head3 データベースの関数やストアドプロシージャを使う | |
253 | 122 | |
254 | =begin original | |
255 | ||
256 | 123 | The combination of C<select> and C<as> can be used to return the result of a |
257 | 124 | database function or stored procedure as a column value. You use C<select> to |
258 | 125 | specify the source for your column value (e.g. a column name, function, or |
259 | 126 | stored procedure name). You then use C<as> to set the column name you will use |
260 | 127 | to access the returned value: |
261 | 128 | |
262 | =end original | |
263 | ||
264 | 129 | C<select>とC<as>の組み合わせで、カラムの値としてデータベース関数やストアド |
265 | 130 | プロシージャの結果を返すのに使うことが出来ます。C<select>を使って、カラムの |
266 | 131 | 値のためのソースを指定できます(例えば、カラム名、関数、ストアドプロシージャ名)。 |
267 | 132 | それから、C<as>を、返された値にアクセスするのに使うカラム名をセットするのに |
268 | 133 | 使えます: |
269 | 134 | |
270 | 135 | my $rs = $schema->resultset('Artist')->search( |
271 | 136 | {}, |
272 | 137 | { |
273 | 138 | select => [ 'name', { LENGTH => 'name' } ], |
274 | 139 | as => [qw/ name name_length /], |
275 | 140 | } |
276 | 141 | ); |
277 | 142 | |
278 | 143 | # Equivalent SQL: |
279 | 144 | # SELECT name name, LENGTH( name ) |
280 | 145 | # FROM artist |
281 | 146 | |
282 | Note that the C<as> attribute | |
147 | Note that the C< as > attribute has absolutely nothing to with the sql | |
283 | 148 | syntax C< SELECT foo AS bar > (see the documentation in |
284 | L<DBIx::Class::ResultSet/ATTRIBUTES>). | |
149 | L<DBIx::Class::ResultSet/ATTRIBUTES>). If your alias exists as a | |
285 | ||
150 | column in your base class (i.e. it was added with C<add_columns>), you | |
151 | just access it as normal. Our C<Artist> class has a C<name> column, so | |
152 | we just use the C<name> accessor: | |
286 | 153 | |
287 | my $rs = $schema->resultset('Artist')->search( | |
288 | {}, | |
289 | { | |
290 | join => 'cds', | |
291 | distinct => 1, | |
292 | '+select' => [ { count => 'cds.cdid', -as => 'amount_of_cds' } ], | |
293 | '+as' => [qw/num_cds/], | |
294 | order_by => { -desc => 'amount_of_cds' }, | |
295 | } | |
296 | ); | |
297 | ||
298 | # Equivalent SQL | |
299 | # SELECT me.artistid, me.name, me.rank, me.charfield, COUNT( cds.cdid ) AS amount_of_cds | |
300 | # FROM artist me LEFT JOIN cd cds ON cds.artist = me.artistid | |
301 | # GROUP BY me.artistid, me.name, me.rank, me.charfield | |
302 | # ORDER BY amount_of_cds DESC | |
303 | ||
304 | =begin original | |
305 | ||
306 | If your alias exists as a column in your base class (i.e. it was added with | |
307 | L<add_columns|DBIx::Class::ResultSource/add_columns>), you just access it as | |
308 | normal. Our C<Artist> class has a C<name> column, so we just use the C<name> | |
309 | accessor: | |
310 | ||
311 | =end original | |
312 | ||
313 | 154 | C< as >属性は、SQLのシンタックスC< SELECT foo AS bar>とまったく関係ないことに |
314 | 155 | 気をつけてください(L<DBIx::Class::ResultSet/ATTRIBUTES>のドキュメントを見てください)。 |
315 | 156 | ベースクラスにカラムとしてエイリアスがある(すなわち、C<add_columns>で追加されている)のなら、 |
316 | 157 | 普通にそれにアクセスできます。この例で言えば、C<Artist>クラスには、 |
317 | 158 | C<name>カラムがあるので、C<name>アクセサを使えます: |
318 | 159 | |
319 | 160 | my $artist = $rs->first(); |
320 | 161 | my $name = $artist->name(); |
321 | 162 | |
322 | =begin original | |
323 | ||
324 | 163 | If on the other hand the alias does not correspond to an existing column, you |
325 | 164 | have to fetch the value using the C<get_column> accessor: |
326 | 165 | |
327 | =end original | |
328 | ||
329 | 166 | 一方で、エイリアスが既存のカラムに一致しないなら、C<get_column>アクセサを使って、 |
330 | 167 | 値を取得する必要があります: |
331 | 168 | |
332 | 169 | my $name_length = $artist->get_column('name_length'); |
333 | 170 | |
334 | =begin original | |
335 | ||
336 | 171 | If you don't like using C<get_column>, you can always create an accessor for |
337 | 172 | any of your aliases using either of these: |
338 | 173 | |
339 | =end original | |
340 | ||
341 | 174 | C<get_column>が気に入らなければ、いつでも、下記のいずれかを使ってどんな |
342 | 175 | エイリアスにもアクセサを作れます: |
343 | 176 | |
344 | 177 | # Define accessor manually: |
345 | 178 | sub name_length { shift->get_column('name_length'); } |
179 | ||
347 | 180 | # Or use DBIx::Class::AccessorGroup: |
348 | 181 | __PACKAGE__->mk_group_accessors('column' => 'name_length'); |
349 | 182 | |
350 | ||
183 | =head3 SELECT DISTINCT with multiple columns | |
351 | 184 | |
352 | ||
185 | my $rs = $schema->resultset('Foo')->search( | |
353 | ||
354 | my $rs = $schema->resultset('Artist')->search( | |
355 | 186 | {}, |
356 | 187 | { |
357 | | |
188 | select => [ | |
358 | distinct => | |
189 | { distinct => [ $source->columns ] } | |
190 | ], | |
191 | as => [ $source->columns ] # remember 'as' is not the same as SQL AS :-) | |
359 | 192 | } |
360 | 193 | ); |
361 | 194 | |
362 | my $ | |
195 | my $count = $rs->next->get_column('count'); | |
363 | {}, | |
364 | { | |
365 | columns => [ qw/artist_id name rank/ ], | |
366 | group_by => [ qw/artist_id name rank/ ], | |
367 | } | |
368 | ); | |
369 | 196 | |
370 | | |
197 | =head3 SELECT COUNT(DISTINCT colname) | |
371 | # SELECT me.artist_id, me.name, me.rank | |
372 | # FROM artist me | |
373 | # GROUP BY artist_id, name, rank | |
374 | 198 | |
375 | ||
199 | my $rs = $schema->resultset('Foo')->search( | |
376 | ||
377 | my $rs = $schema->resultset('Artist')->search( | |
378 | 200 | {}, |
379 | 201 | { |
380 | | |
202 | select => [ | |
381 | distinct => | |
203 | { count => { distinct => 'colname' } } | |
204 | ], | |
205 | as => [ 'count' ] | |
382 | 206 | } |
383 | 207 | ); |
384 | 208 | |
385 | ||
209 | =head3 結果のグルーピング | |
386 | {}, | |
387 | { | |
388 | columns => [ qw/name/ ], | |
389 | group_by => [ qw/name/ ], | |
390 | } | |
391 | ); | |
392 | 210 | |
393 | my $count = $rs->count; | |
394 | ||
395 | # Equivalent SQL: | |
396 | # SELECT COUNT( * ) FROM (SELECT me.name FROM artist me GROUP BY me.name) me: | |
397 | ||
398 | =head2 結果のグルーピング | |
399 | ||
400 | 211 | L<DBIx::Class> supports C<GROUP BY> as follows: |
401 | 212 | |
402 | 213 | L<DBIx::Class>はC<GROUP BY>をサポートします: |
403 | 214 | |
404 | 215 | my $rs = $schema->resultset('Artist')->search( |
405 | 216 | {}, |
406 | 217 | { |
407 | 218 | join => [qw/ cds /], |
408 | select => [ 'name', { count => 'cds.id' } ], | |
219 | select => [ 'name', { count => 'cds.cdid' } ], | |
409 | 220 | as => [qw/ name cd_count /], |
410 | 221 | group_by => [qw/ name /] |
411 | 222 | } |
412 | 223 | ); |
413 | 224 | |
414 | 225 | # Equivalent SQL: |
415 | # SELECT name, COUNT( cd.id ) FROM artist | |
226 | # SELECT name, COUNT( cds.cdid ) FROM artist me | |
416 | # LEFT JOIN cd ON artist | |
227 | # LEFT JOIN cd cds ON ( cds.artist = me.artistid ) | |
417 | 228 | # GROUP BY name |
418 | 229 | |
419 | =begin original | |
420 | ||
421 | 230 | Please see L<DBIx::Class::ResultSet/ATTRIBUTES> documentation if you |
422 | 231 | are in any way unsure about the use of the attributes above (C< join |
423 | 232 | >, C< select >, C< as > and C< group_by >). |
424 | 233 | |
425 | =end original | |
426 | ||
427 | 234 | 上記の(C< join >、 C< select >、 C< as >、 C< group_by>)属性の使い方がわからなければ、 |
428 | 235 | L<DBIx::Class::ResultSet/ATTRIBUTES>ドキュメントをみてください。 |
429 | 236 | |
430 | =head | |
237 | =head3 定義済み検索 | |
431 | 238 | |
432 | You can write | |
239 | You can write your own L<DBIx::Class::ResultSet> class by inheriting from it | |
240 | and define often used searches as methods: | |
433 | 241 | |
434 | my $inside_rs = $schema->resultset('Artist')->search({ | |
435 | name => [ 'Billy Joel', 'Brittany Spears' ], | |
436 | }); | |
437 | ||
438 | my $rs = $schema->resultset('CD')->search({ | |
439 | artist_id => { 'IN' => $inside_rs->get_column('id')->as_query }, | |
440 | }); | |
441 | ||
442 | The usual operators ( =, !=, IN, NOT IN, etc.) are supported. | |
443 | ||
444 | B<NOTE>: You have to explicitly use '=' when doing an equality comparison. | |
445 | The following will B<not> work: | |
446 | ||
447 | my $rs = $schema->resultset('CD')->search({ | |
448 | artist_id => $inside_rs->get_column('id')->as_query, # does NOT work | |
449 | }); | |
450 | ||
451 | =head3 Support | |
452 | ||
453 | Subqueries are supported in the where clause (first hashref), and in the | |
454 | from, select, and +select attributes. | |
455 | ||
456 | =head3 Correlated subqueries | |
457 | ||
458 | my $cdrs = $schema->resultset('CD'); | |
459 | my $rs = $cdrs->search({ | |
460 | year => { | |
461 | '=' => $cdrs->search( | |
462 | { artist_id => { '=' => { -ident => 'me.artist_id' } } }, | |
463 | { alias => 'inner' } | |
464 | )->get_column('year')->max_rs->as_query, | |
465 | }, | |
466 | }); | |
467 | ||
468 | That creates the following SQL: | |
469 | ||
470 | SELECT me.cdid, me.artist, me.title, me.year, me.genreid, me.single_track | |
471 | FROM cd me | |
472 | WHERE year = ( | |
473 | SELECT MAX(inner.year) | |
474 | FROM cd inner | |
475 | WHERE artist_id = me.artist_id | |
476 | ) | |
477 | ||
478 | =head2 定義済み検索 | |
479 | ||
480 | =begin original | |
481 | ||
482 | You can define frequently used searches as methods by subclassing | |
483 | L<DBIx::Class::ResultSet>: | |
484 | ||
485 | =end original | |
486 | ||
487 | 242 | L<DBIx::Class::ResultSet>クラスを継承して、自分自身のクラスを書き、よく使う |
488 | 243 | 検索をメソッドとして定義できます: |
489 | 244 | |
490 | 245 | package My::DBIC::ResultSet::CD; |
491 | 246 | use strict; |
492 | 247 | use warnings; |
493 | 248 | use base 'DBIx::Class::ResultSet'; |
494 | 249 | |
495 | 250 | sub search_cds_ordered { |
496 | 251 | my ($self) = @_; |
497 | 252 | |
498 | 253 | return $self->search( |
499 | 254 | {}, |
500 | 255 | { order_by => 'name DESC' }, |
501 | 256 | ); |
502 | 257 | } |
503 | 258 | |
504 | 259 | 1; |
505 | 260 | |
506 | ||
261 | To use your resultset, first tell DBIx::Class to create an instance of it | |
507 | ||
262 | for you, in your My::DBIC::Schema::CD class: | |
508 | be automatically loaded. | |
509 | 263 | |
510 | =begin original | |
511 | ||
512 | If however you are still using L<DBIx::Class::Schema/load_classes>, first tell | |
513 | DBIx::Class to create an instance of the ResultSet class for you, in your | |
514 | My::DBIC::Schema::CD class: | |
515 | ||
516 | =end original | |
517 | ||
518 | 264 | 自分の結果セット使うには、最初に、自分のMy::DBIC::Schema::CDクラスの中で、 |
519 | 265 | DBIx::Classにそのインスタンスを作るように教えます。 |
520 | 266 | |
521 | # class definition as normal | |
522 | use base 'DBIx::Class::Core'; | |
523 | __PACKAGE__->table('cd'); | |
524 | ||
525 | # tell DBIC to use the custom ResultSet class | |
526 | 267 | __PACKAGE__->resultset_class('My::DBIC::ResultSet::CD'); |
527 | 268 | |
528 | Note that C<resultset_class> must be called after C<load_components> and C<table>, or you will get errors about missing methods. | |
529 | ||
530 | =begin original | |
531 | ||
532 | 269 | Then call your new method in your code: |
533 | 270 | |
534 | =end original | |
535 | ||
536 | 271 | それから、コードの中で、新しいメソッドを呼びます: |
537 | 272 | |
538 | 273 | my $ordered_cds = $schema->resultset('CD')->search_cds_ordered(); |
539 | 274 | |
540 | =head2 Using SQL functions on the left hand side of a comparison | |
541 | 275 | |
542 | ||
276 | =head3 ResultSetクラスを書かかない、先に定義された検索 | |
543 | good idea since it requires a scan of the entire table. (Unless your RDBMS | |
544 | supports indexes on expressions - including return values of functions - and | |
545 | you create an index on the return value of the function in question.) However, | |
546 | it can be accomplished with C<DBIx::Class> when necessary by resorting to | |
547 | literal SQL: | |
548 | 277 | |
549 | ||
278 | Alternatively you can automatically generate a DBIx::Class::ResultSet | |
279 | class by using the ResultSetManager component and tagging your method | |
280 | as ResultSet: | |
550 | 281 | |
551 | ||
282 | 別のやりかたとして、ResultSetManagerコンポーネントを使い、ResultSetとして | |
552 | ||
283 | 自分のメソッドをタギングすることで、DBIx::Class::ResultSetクラスを自動的に作れます。 | |
553 | 284 | |
554 | | |
285 | __PACKAGE__->load_components(qw/ ResultSetManager Core /); | |
555 | name => 'Bob', | |
556 | \[ 'YEAR(date_of_birth) = ?', [ plain_value => 1979 ] ], | |
557 | ]}); | |
558 | 286 | |
559 | | |
287 | sub search_cds_ordered : ResultSet { | |
560 | | |
288 | my ($self) = @_; | |
289 | return $self->search( | |
290 | {}, | |
291 | { order_by => 'name DESC' }, | |
292 | ); | |
293 | } | |
561 | 294 | |
562 | ||
295 | Then call your method in the same way from your code: | |
563 | should be either the same as the name of the column (do this if the type of the | |
564 | return value of the function is the same as the type of the column) or in the | |
565 | case of a function it's currently treated as a dummy string (it is a good idea | |
566 | to use C<plain_value> or something similar to convey intent). The value is | |
567 | currently only significant when handling special column types (BLOBs, arrays, | |
568 | etc.), but this may change in the future. | |
569 | 296 | |
570 | ||
297 | これで、コードから同じ方法で呼べます: | |
571 | (subqueries)>. | |
572 | 298 | |
299 | my $ordered_cds = $schema->resultset('CD')->search_cds_ordered(); | |
573 | 300 | |
574 | =head1 JOINS AND PREFETCHING | |
575 | ||
576 | 301 | =head2 joins と prefetch を使う |
577 | 302 | |
578 | =begin original | |
579 | ||
580 | 303 | You can use the C<join> attribute to allow searching on, or sorting your |
581 | results by, one or more columns in a related table. | |
304 | results by, one or more columns in a related table. To return all CDs matching | |
305 | a particular artist name: | |
582 | 306 | |
583 | =end original | |
584 | ||
585 | 307 | C<join>属性を使って、関連するテーブルの1つ以上のカラムを使って、 |
586 | 検索や、結果のソートができます。 | |
308 | 検索や、結果のソートができます。特定のアーティスト名の全てのCDを | |
309 | 返すためには: | |
587 | 310 | |
588 | This requires that you have defined the L<DBIx::Class::Relationship>. For example : | |
589 | ||
590 | L<DBIx::Class::Relationship>を定義する必要があります。例えば: | |
591 | ||
592 | My::Schema::CD->has_many( artists => 'My::Schema::Artist', 'artist_id'); | |
593 | ||
594 | =begin original | |
595 | ||
596 | To return all CDs matching a particular artist name, you specify the name of the relationship ('artists'): | |
597 | ||
598 | =end original | |
599 | ||
600 | 特定のアーティスト名の全てのCDを返すためには: | |
601 | ||
602 | ||
603 | 311 | my $rs = $schema->resultset('CD')->search( |
604 | 312 | { |
605 | 'artist | |
313 | 'artist.name' => 'Bob Marley' | |
606 | 314 | }, |
607 | 315 | { |
608 | join => | |
316 | join => [qw/artist/], # join the artist table | |
609 | 317 | } |
610 | 318 | ); |
611 | 319 | |
612 | 320 | # Equivalent SQL: |
613 | 321 | # SELECT cd.* FROM cd |
614 | 322 | # JOIN artist ON cd.artist = artist.id |
615 | 323 | # WHERE artist.name = 'Bob Marley' |
616 | 324 | |
617 | In that example both the join, and the condition use the relationship name rather than the table name | |
618 | (see L<DBIx::Class::Manual::Joining> for more details on aliasing ). | |
619 | ||
620 | =begin original | |
621 | ||
622 | 325 | If required, you can now sort on any column in the related tables by including |
623 | it in your C<order_by> attribute | |
326 | it in your C<order_by> attribute: | |
624 | 327 | |
625 | =end original | |
626 | ||
627 | 328 | 必要なら、C<order_by>属性にそれを含めて、関連するテーブルのいずれかのカラムで |
628 | ソートすることも出来ます | |
329 | ソートすることも出来ます。 | |
629 | 330 | |
630 | 331 | my $rs = $schema->resultset('CD')->search( |
631 | 332 | { |
632 | 'artist | |
333 | 'artist.name' => 'Bob Marley' | |
633 | 334 | }, |
634 | 335 | { |
635 | join => | |
336 | join => [qw/ artist /], | |
636 | order_by => [qw/ artist | |
337 | order_by => [qw/ artist.name /] | |
637 | 338 | } |
638 | | |
339 | }; | |
639 | 340 | |
640 | 341 | # Equivalent SQL: |
641 | 342 | # SELECT cd.* FROM cd |
642 | 343 | # JOIN artist ON cd.artist = artist.id |
643 | 344 | # WHERE artist.name = 'Bob Marley' |
644 | 345 | # ORDER BY artist.name |
645 | 346 | |
646 | =begin original | |
647 | ||
648 | 347 | Note that the C<join> attribute should only be used when you need to search or |
649 | 348 | sort using columns in a related table. Joining related tables when you only |
650 | 349 | need columns from the main table will make performance worse! |
651 | 350 | |
652 | =end original | |
653 | ||
654 | 351 | C<join>属性は関連するテーブルのカラムを使って検索やソートをする必要があるときにのみ |
655 | 352 | 使われるべきだということに注意してください。 |
656 | 353 | メインのテーブルからカラムが必要なときに、関連するテーブルを結合するのは、 |
657 | 354 | パフォーマンスが悪いです! |
658 | 355 | |
659 | =begin original | |
660 | ||
661 | 356 | Now let's say you want to display a list of CDs, each with the name of the |
662 | 357 | artist. The following will work fine: |
663 | 358 | |
664 | =end original | |
665 | ||
666 | 359 | で、、CDのリストを、それぞれのアーティストの名前と一緒に表示したいとしましょう。 |
667 | 360 | 下記のやりかたでうまくいきます: |
668 | 361 | |
669 | 362 | while (my $cd = $rs->next) { |
670 | 363 | print "CD: " . $cd->title . ", Artist: " . $cd->artist->name; |
671 | 364 | } |
672 | 365 | |
673 | =begin original | |
674 | ||
675 | 366 | There is a problem however. We have searched both the C<cd> and C<artist> tables |
676 | 367 | in our main query, but we have only returned data from the C<cd> table. To get |
677 | 368 | the artist name for any of the CD objects returned, L<DBIx::Class> will go back |
678 | 369 | to the database: |
679 | 370 | |
680 | =end original | |
681 | ||
682 | 371 | ですが、一つ問題があります。このメインクエリで、C<cd>とC<artist>テーブルの両方を |
683 | 372 | 検索していますが、C<cd>からのみデータが返されています。返されたCDオブジェクトの一部で、 |
684 | 373 | アーティスト名を得るために、L<DBIx::Class>は、データベースに戻ります: |
685 | 374 | |
686 | 375 | SELECT artist.* FROM artist WHERE artist.id = ? |
687 | 376 | |
688 | =begin original | |
689 | ||
690 | 377 | A statement like the one above will run for each and every CD returned by our |
691 | 378 | main query. Five CDs, five extra queries. A hundred CDs, one hundred extra |
692 | 379 | queries! |
693 | 380 | |
694 | =end original | |
695 | ||
696 | 381 | 上記のようなステートメントが、メインクエリによって返された、それぞれの、全ての |
697 | 382 | CDで走ります。5つのCDであれば、5つの別のクエリです。100のCDであれば、100の別の |
698 | 383 | クエリ! |
699 | 384 | |
700 | =begin original | |
701 | ||
702 | 385 | Thankfully, L<DBIx::Class> has a C<prefetch> attribute to solve this problem. |
703 | 386 | This allows you to fetch results from related tables in advance: |
704 | 387 | |
705 | =end original | |
706 | ||
707 | 388 | ありがたいことに、L<DBIx::Class>は、C<prefetch>属性があり、この問題を解決できます。 |
708 | 389 | この属性を使うと、先に関連するテーブルから結果をとってこれます: |
709 | 390 | |
710 | 391 | |
711 | 392 | my $rs = $schema->resultset('CD')->search( |
712 | 393 | { |
713 | 'artist | |
394 | 'artist.name' => 'Bob Marley' | |
714 | 395 | }, |
715 | 396 | { |
716 | join => | |
397 | join => [qw/ artist /], | |
717 | order_by => [qw/ artist | |
398 | order_by => [qw/ artist.name /], | |
718 | prefetch => | |
399 | prefetch => [qw/ artist /] # return artist data too! | |
719 | 400 | } |
720 | 401 | ); |
721 | 402 | |
722 | 403 | # Equivalent SQL (note SELECT from both "cd" and "artist"): |
723 | 404 | # SELECT cd.*, artist.* FROM cd |
724 | 405 | # JOIN artist ON cd.artist = artist.id |
725 | 406 | # WHERE artist.name = 'Bob Marley' |
726 | 407 | # ORDER BY artist.name |
727 | 408 | |
728 | =begin original | |
729 | ||
730 | 409 | The code to print the CD list remains the same: |
731 | 410 | |
732 | =end original | |
733 | ||
734 | 411 | CDのリストを表示するコードは同じ物が使えます: |
735 | 412 | |
736 | 413 | while (my $cd = $rs->next) { |
737 | 414 | print "CD: " . $cd->title . ", Artist: " . $cd->artist->name; |
738 | 415 | } |
739 | 416 | |
740 | =begin original | |
741 | ||
742 | 417 | L<DBIx::Class> has now prefetched all matching data from the C<artist> table, |
743 | 418 | so no additional SQL statements are executed. You now have a much more |
744 | 419 | efficient query. |
745 | 420 | |
746 | =end original | |
747 | ||
748 | 421 | L<DBIx::Class>はC<artist>テーブルからすべてのマッチするデータを先にとってきています。 |
749 | 422 | そのため、余分なSQLステートメントは実行されません。より効率的なクエリになりました。 |
750 | 423 | |
751 | ||
424 | Note that as of L<DBIx::Class> 0.05999_01, C<prefetch> I<can> be used with | |
425 | C<has_many> relationships. | |
752 | 426 | |
427 | L<DBIx::Class> 0.05999_01の時点で、 C<has_many>のリレーションシップで、 | |
428 | C<prefetch>をI<使え>たのに注意してください。 | |
429 | ||
753 | 430 | Also note that C<prefetch> should only be used when you know you will |
754 | 431 | definitely use data from a related table. Pre-fetching related tables when you |
755 | 432 | only need columns from the main table will make performance worse! |
756 | 433 | |
757 | =end original | |
758 | 434 | |
759 | 435 | また、C<prefetch>は、関連するテーブルからデータを必ず使うとわかっているときのみに、 |
760 | 436 | 使うべきです。メインテーブルからのカラムしか必要としないなら、 |
761 | 437 | 関連するテーブルから先に取得するのは、パフォーマンスを悪くします! |
762 | 438 | |
763 | =head | |
439 | =head3 マルチステップの結合(join) | |
764 | 440 | |
765 | In the examples above, the C<join> attribute was a scalar. If you | |
766 | pass an array reference instead, you can join to multiple tables. In | |
767 | this example, we want to limit the search further, using | |
768 | C<LinerNotes>: | |
769 | ||
770 | # Relationships defined elsewhere: | |
771 | # CD->belongs_to('artist' => 'Artist'); | |
772 | # CD->has_one('liner_notes' => 'LinerNotes', 'cd'); | |
773 | my $rs = $schema->resultset('CD')->search( | |
774 | { | |
775 | 'artist.name' => 'Bob Marley' | |
776 | 'liner_notes.notes' => { 'like', '%some text%' }, | |
777 | }, | |
778 | { | |
779 | join => [qw/ artist liner_notes /], | |
780 | order_by => [qw/ artist.name /], | |
781 | } | |
782 | ); | |
783 | ||
784 | # Equivalent SQL: | |
785 | # SELECT cd.*, artist.*, liner_notes.* FROM cd | |
786 | # JOIN artist ON cd.artist = artist.id | |
787 | # JOIN liner_notes ON cd.id = liner_notes.cd | |
788 | # WHERE artist.name = 'Bob Marley' | |
789 | # ORDER BY artist.name | |
790 | ||
791 | =head2 マルチステップの結合(join) | |
792 | ||
793 | =begin original | |
794 | ||
795 | 441 | Sometimes you want to join more than one relationship deep. In this example, |
796 | 442 | we want to find all C<Artist> objects who have C<CD>s whose C<LinerNotes> |
797 | 443 | contain a specific string: |
798 | 444 | |
799 | =end original | |
800 | ||
801 | 445 | 2つ以上の深いリレーションシップでjoinしたいときもあるでしょう。 |
802 | 446 | この例では、C<LinerNotes>に特定の文字が含まれるC<CD>を持っている、 |
803 | 447 | C<Artist>オブジェクトを探したいとします: |
804 | 448 | |
805 | 449 | # Relationships defined elsewhere: |
806 | 450 | # Artist->has_many('cds' => 'CD', 'artist'); |
807 | 451 | # CD->has_one('liner_notes' => 'LinerNotes', 'cd'); |
808 | 452 | |
809 | 453 | my $rs = $schema->resultset('Artist')->search( |
810 | 454 | { |
811 | 455 | 'liner_notes.notes' => { 'like', '%some text%' }, |
812 | 456 | }, |
813 | 457 | { |
814 | 458 | join => { |
815 | 459 | 'cds' => 'liner_notes' |
816 | 460 | } |
817 | 461 | } |
818 | 462 | ); |
819 | 463 | |
820 | 464 | # Equivalent SQL: |
821 | 465 | # SELECT artist.* FROM artist |
822 | # | |
466 | # JOIN ( cd ON artist.id = cd.artist ) | |
823 | # | |
467 | # JOIN ( liner_notes ON cd.id = liner_notes.cd ) | |
824 | 468 | # WHERE liner_notes.notes LIKE '%some text%' |
825 | 469 | |
826 | =begin original | |
827 | ||
828 | 470 | Joins can be nested to an arbitrary level. So if we decide later that we |
829 | 471 | want to reduce the number of Artists returned based on who wrote the liner |
830 | 472 | notes: |
831 | 473 | |
832 | =end original | |
833 | ||
834 | 474 | 結合は任意のレベルでネストできます。ですので、後から、ライナーノーツを |
835 | 475 | 誰が書いたかを元に、返されるアーティストの数を減らしたいと決めたとしたら: |
836 | 476 | |
837 | 477 | # Relationship defined elsewhere: |
838 | 478 | # LinerNotes->belongs_to('author' => 'Person'); |
839 | 479 | |
840 | 480 | my $rs = $schema->resultset('Artist')->search( |
841 | 481 | { |
842 | 482 | 'liner_notes.notes' => { 'like', '%some text%' }, |
843 | 483 | 'author.name' => 'A. Writer' |
844 | 484 | }, |
845 | 485 | { |
846 | 486 | join => { |
847 | 487 | 'cds' => { |
848 | 488 | 'liner_notes' => 'author' |
849 | 489 | } |
850 | 490 | } |
851 | 491 | } |
852 | 492 | ); |
853 | 493 | |
854 | 494 | # Equivalent SQL: |
855 | 495 | # SELECT artist.* FROM artist |
856 | # | |
496 | # JOIN ( cd ON artist.id = cd.artist ) | |
857 | # | |
497 | # JOIN ( liner_notes ON cd.id = liner_notes.cd ) | |
858 | # | |
498 | # JOIN ( author ON author.id = liner_notes.author ) | |
859 | 499 | # WHERE liner_notes.notes LIKE '%some text%' |
860 | 500 | # AND author.name = 'A. Writer' |
861 | 501 | |
862 | =head2 マルチステップ | |
502 | =head2 マルチステップのprefetch | |
863 | 503 | |
864 | ||
504 | From 0.04999_05 onwards, C<prefetch> can be nested more than one relationship | |
865 | tables in any combination you desire. For example, to join Artist to | |
866 | CD and Concert, and join CD to LinerNotes: | |
867 | ||
868 | # Relationships defined elsewhere: | |
869 | # Artist->has_many('concerts' => 'Concert', 'artist'); | |
870 | ||
871 | my $rs = $schema->resultset('Artist')->search( | |
872 | { }, | |
873 | { | |
874 | join => [ | |
875 | { | |
876 | cds => 'liner_notes' | |
877 | }, | |
878 | 'concerts' | |
879 | ], | |
880 | } | |
881 | ); | |
882 | ||
883 | # Equivalent SQL: | |
884 | # SELECT artist.* FROM artist | |
885 | # LEFT JOIN cd ON artist.id = cd.artist | |
886 | # LEFT JOIN liner_notes ON cd.id = liner_notes.cd | |
887 | # LEFT JOIN concert ON artist.id = concert.artist | |
888 | ||
889 | =head2 Multi-step prefetch | |
890 | ||
891 | =begin original | |
892 | ||
893 | C<prefetch> can be nested more than one relationship | |
894 | 505 | deep using the same syntax as a multi-step join: |
895 | 506 | |
896 | ||
507 | 0.04999_05から、C<prefetch>は、マルチステップの結合と同じシンタックスで、 | |
897 | ||
898 | C<prefetch>は、マルチステップの結合と同じシンタックスで、 | |
899 | 508 | 2つ以上の深いリレーションシップでネストできました: |
900 | 509 | |
901 | 510 | my $rs = $schema->resultset('Tag')->search( |
902 | 511 | {}, |
903 | 512 | { |
904 | 513 | prefetch => { |
905 | 514 | cd => 'artist' |
906 | 515 | } |
907 | 516 | } |
908 | 517 | ); |
909 | 518 | |
910 | 519 | # Equivalent SQL: |
911 | 520 | # SELECT tag.*, cd.*, artist.* FROM tag |
912 | # JOIN cd ON tag.cd = cd.id | |
521 | # JOIN cd ON tag.cd = cd.cdid | |
913 | # JOIN artist ON cd.artist = artist.id | |
522 | # JOIN artist ON cd.artist = artist.artistid | |
914 | 523 | |
915 | =begin original | |
916 | ||
917 | 524 | Now accessing our C<cd> and C<artist> relationships does not need additional |
918 | 525 | SQL statements: |
919 | 526 | |
920 | =end original | |
921 | 527 | |
922 | ||
923 | 528 | これで、C<cd>とC<artist>のリレーションシップにアクセスするのに、 |
924 | 529 | 追加のSQLステートメントは必要ありません: |
925 | 530 | |
926 | 531 | my $tag = $rs->first; |
927 | 532 | print $tag->cd->artist->name; |
928 | 533 | |
929 | =head | |
534 | =head2 Columns of data | |
930 | 535 | |
931 | =head2 列オブジェクトのスキーマを得る | |
932 | ||
933 | =begin original | |
934 | ||
935 | It is possible to get a Schema object from a row object like so: | |
936 | ||
937 | =end original | |
938 | ||
939 | 次のようにして、列のオブジェクトからスキーマを得ることができます: | |
940 | ||
941 | my $schema = $cd->result_source->schema; | |
942 | # use the schema as normal: | |
943 | my $artist_rs = $schema->resultset('Artist'); | |
944 | ||
945 | =begin original | |
946 | ||
947 | This can be useful when you don't want to pass around a Schema object to every | |
948 | method. | |
949 | ||
950 | =end original | |
951 | ||
952 | 全てのメソッドで、スキーマオブジェクトを順に回したくなければ、便利でしょう。 | |
953 | ||
954 | =head2 最後にデータベースにインサートしたプライマリキーの値を取りたい | |
955 | ||
956 | =begin original | |
957 | ||
958 | AKA getting last_insert_id | |
959 | ||
960 | =end original | |
961 | ||
962 | last_insert_id を取るともいいます。 | |
963 | ||
964 | =begin original | |
965 | ||
966 | Thanks to the core component PK::Auto, this is straightforward: | |
967 | ||
968 | =end original | |
969 | ||
970 | コアコンポーネントのPK::Autoに感謝して、直接: | |
971 | ||
972 | my $foo = $rs->create(\%blah); | |
973 | # do more stuff | |
974 | my $id = $foo->id; # foo->my_primary_key_field will also work. | |
975 | ||
976 | =begin original | |
977 | ||
978 | If you are not using autoincrementing primary keys, this will probably | |
979 | not work, but then you already know the value of the last primary key anyway. | |
980 | ||
981 | =end original | |
982 | ||
983 | オートインクリメントのプライマリキーを使っていないのなら、おそらく動きません。 | |
984 | ですが、その場合は、すでに、プライマリキーの値を知っていることでしょう。 | |
985 | ||
986 | =head2 Stringification | |
987 | ||
988 | =begin original | |
989 | ||
990 | Employ the standard stringification technique by using the L<overload> | |
991 | module. | |
992 | ||
993 | =end original | |
994 | ||
995 | C<overload> モジュールで標準的な文字列化のテクニックを使えます。 | |
996 | ||
997 | =begin original | |
998 | ||
999 | To make an object stringify itself as a single column, use something | |
1000 | like this (replace C<name> with the column/method of your choice): | |
1001 | ||
1002 | =end original | |
1003 | ||
1004 | ひとつのカラムについて、オブジェクト自身を文字列化するには、 | |
1005 | 次のようにします。(カラム/メソッドでC<name>を置き換えてください) | |
1006 | ||
1007 | use overload '""' => sub { shift->name}, fallback => 1; | |
1008 | ||
1009 | =begin original | |
1010 | ||
1011 | For more complex stringification, you can use an anonymous subroutine: | |
1012 | ||
1013 | =end original | |
1014 | ||
1015 | より複雑な文字列化では、無名サブルーチンを使えます: | |
1016 | ||
1017 | use overload '""' => sub { $_[0]->name . ", " . | |
1018 | $_[0]->address }, fallback => 1; | |
1019 | ||
1020 | =head3 文字列化の例 | |
1021 | ||
1022 | =begin original | |
1023 | ||
1024 | Suppose we have two tables: C<Product> and C<Category>. The table | |
1025 | specifications are: | |
1026 | ||
1027 | =end original | |
1028 | ||
1029 | 二つのテーブルがあるとします:C<Product>とC<Cateogry>。 | |
1030 | テーブルの定義は次の通り: | |
1031 | ||
1032 | Product(id, Description, category) | |
1033 | Category(id, Description) | |
1034 | ||
1035 | =begin original | |
1036 | ||
1037 | C<category> is a foreign key into the Category table. | |
1038 | ||
1039 | =end original | |
1040 | ||
1041 | C<category>はCategoryテーブルの外部キーです。 | |
1042 | ||
1043 | =begin original | |
1044 | ||
1045 | If you have a Product object C<$obj> and write something like | |
1046 | ||
1047 | =end original | |
1048 | ||
1049 | ProductオブジェクトC<$obj>があり、次のように書いたとすると、 | |
1050 | ||
1051 | print $obj->category | |
1052 | ||
1053 | =begin original | |
1054 | ||
1055 | things will not work as expected. | |
1056 | ||
1057 | =end original | |
1058 | ||
1059 | 期待どおりには動きません。 | |
1060 | ||
1061 | =begin original | |
1062 | ||
1063 | To obtain, for example, the category description, you should add this | |
1064 | method to the class defining the Category table: | |
1065 | ||
1066 | =end original | |
1067 | ||
1068 | カテゴリの内容を得たいなら、例えば、Categoryテーブルのクラス定義に次の | |
1069 | メソッドを追加すべきです: | |
1070 | ||
1071 | use overload "" => sub { | |
1072 | my $self = shift; | |
1073 | ||
1074 | return $self->Description; | |
1075 | }, fallback => 1; | |
1076 | ||
1077 | =head2 find_or_create が見付けたのか、列を作ったのかを知りたい? | |
1078 | ||
1079 | =begin original | |
1080 | ||
1081 | Just use C<find_or_new> instead, then check C<in_storage>: | |
1082 | ||
1083 | =end original | |
1084 | ||
1085 | C<find_or_new>を代わりに使ってください。それから、C<in_storage>をチェックします: | |
1086 | ||
1087 | my $obj = $rs->find_or_new({ blah => 'blarg' }); | |
1088 | unless ($obj->in_storage) { | |
1089 | $obj->insert; | |
1090 | # do whatever else you wanted if it was a new row | |
1091 | } | |
1092 | ||
1093 | =head2 Static sub-classing DBIx::Class result classes | |
1094 | ||
1095 | AKA adding additional relationships/methods/etc. to a model for a | |
1096 | specific usage of the (shared) model. | |
1097 | ||
1098 | B<Schema definition> | |
1099 | ||
1100 | package My::App::Schema; | |
1101 | ||
1102 | use base 'DBIx::Class::Schema'; | |
1103 | ||
1104 | # load subclassed classes from My::App::Schema::Result/ResultSet | |
1105 | __PACKAGE__->load_namespaces; | |
1106 | ||
1107 | # load classes from shared model | |
1108 | load_classes({ | |
1109 | 'My::Shared::Model::Result' => [qw/ | |
1110 | Foo | |
1111 | Bar | |
1112 | /]}); | |
1113 | ||
1114 | 1; | |
1115 | ||
1116 | B<Result-Subclass definition> | |
1117 | ||
1118 | package My::App::Schema::Result::Baz; | |
1119 | ||
1120 | use strict; | |
1121 | use warnings; | |
1122 | use base 'My::Shared::Model::Result::Baz'; | |
1123 | ||
1124 | # WARNING: Make sure you call table() again in your subclass, | |
1125 | # otherwise DBIx::Class::ResultSourceProxy::Table will not be called | |
1126 | # and the class name is not correctly registered as a source | |
1127 | __PACKAGE__->table('baz'); | |
1128 | ||
1129 | sub additional_method { | |
1130 | return "I'm an additional method only needed by this app"; | |
1131 | } | |
1132 | ||
1133 | 1; | |
1134 | ||
1135 | =head2 DBIx::Classのプロキシクラスを動的にサブクラス化する | |
1136 | ||
1137 | =begin original | |
1138 | ||
1139 | AKA multi-class object inflation from one table | |
1140 | ||
1141 | =end original | |
1142 | ||
1143 | AKA 1つのテーブルからマルチクラスのオブジェクトに展開する | |
1144 | ||
1145 | =begin original | |
1146 | ||
1147 | L<DBIx::Class> classes are proxy classes, therefore some different | |
1148 | techniques need to be employed for more than basic subclassing. In | |
1149 | this example we have a single user table that carries a boolean bit | |
1150 | for admin. We would like like to give the admin users | |
1151 | objects (L<DBIx::Class::Row>) the same methods as a regular user but | |
1152 | also special admin only methods. It doesn't make sense to create two | |
1153 | separate proxy-class files for this. We would be copying all the user | |
1154 | methods into the Admin class. There is a cleaner way to accomplish | |
1155 | this. | |
1156 | ||
1157 | =end original | |
1158 | ||
1159 | L<DBIx::Class>クラスはプロキシクラスです。そのため、基本的なサブクラス化以上に、 | |
1160 | いくつかの違ったテクニックが必要とされます。 | |
1161 | この例では、管理者用に真偽値を持っているユーザーテーブルがあります。 | |
1162 | 管理者ユーザーには、オブジェクト(L<DBIx::Class::Row>)のメソッドを、 | |
1163 | 普通のユーザーと同じようにあたえますが、管理者のみの特別なメソッドも、 | |
1164 | あたえたいとします。このために2つのプロキシクラスファイルに分割するのは | |
1165 | 理にかないません。Adminクラスに全てのユーザークラスのメソッドをコピー | |
1166 | することになります。これをするために、よりすっきりした方法があります。 | |
1167 | ||
1168 | =begin original | |
1169 | ||
1170 | Overriding the C<inflate_result> method within the User proxy-class | |
1171 | gives us the effect we want. This method is called by | |
1172 | L<DBIx::Class::ResultSet> when inflating a result from storage. So we | |
1173 | grab the object being returned, inspect the values we are looking for, | |
1174 | bless it if it's an admin object, and then return it. See the example | |
1175 | below: | |
1176 | ||
1177 | =end original | |
1178 | ||
1179 | ユーザーのプロキシクラス内でC<inflate_result>メソッドをオーバーライドすることで、 | |
1180 | 望んでいる効果が得られます。このメソッドは、ストレージから結果が展開されるときに、 | |
1181 | L<DBIx::Class::ResultSet>によって呼ばれます。 | |
1182 | 返されたオブジェクトを掴んだら、探している値を調べ、管理者オブジェクトであれば、 | |
1183 | それをblessして返します。下の例を見てください: | |
1184 | ||
1185 | B<Schema Definition> | |
1186 | ||
1187 | package My::Schema; | |
1188 | ||
1189 | use base qw/DBIx::Class::Schema/; | |
1190 | ||
1191 | __PACKAGE__->load_namespaces; | |
1192 | ||
1193 | 1; | |
1194 | ||
1195 | ||
1196 | B<Proxy-Class definitions> | |
1197 | ||
1198 | package My::Schema::Result::User; | |
1199 | ||
1200 | use strict; | |
1201 | use warnings; | |
1202 | use base qw/DBIx::Class::Core/; | |
1203 | ||
1204 | ### Define what our admin class is, for ensure_class_loaded() | |
1205 | my $admin_class = __PACKAGE__ . '::Admin'; | |
1206 | ||
1207 | __PACKAGE__->table('users'); | |
1208 | ||
1209 | __PACKAGE__->add_columns(qw/user_id email password | |
1210 | firstname lastname active | |
1211 | admin/); | |
1212 | ||
1213 | __PACKAGE__->set_primary_key('user_id'); | |
1214 | ||
1215 | sub inflate_result { | |
1216 | my $self = shift; | |
1217 | my $ret = $self->next::method(@_); | |
1218 | if( $ret->admin ) {### If this is an admin, rebless for extra functions | |
1219 | $self->ensure_class_loaded( $admin_class ); | |
1220 | bless $ret, $admin_class; | |
1221 | } | |
1222 | return $ret; | |
1223 | } | |
1224 | ||
1225 | sub hello { | |
1226 | print "I am a regular user.\n"; | |
1227 | return ; | |
1228 | } | |
1229 | ||
1230 | 1; | |
1231 | ||
1232 | ||
1233 | package My::Schema::Result::User::Admin; | |
1234 | ||
1235 | use strict; | |
1236 | use warnings; | |
1237 | use base qw/My::Schema::Result::User/; | |
1238 | ||
1239 | # This line is important | |
1240 | __PACKAGE__->table('users'); | |
1241 | ||
1242 | sub hello | |
1243 | { | |
1244 | print "I am an admin.\n"; | |
1245 | return; | |
1246 | } | |
1247 | ||
1248 | sub do_admin_stuff | |
1249 | { | |
1250 | print "I am doing admin stuff\n"; | |
1251 | return ; | |
1252 | } | |
1253 | ||
1254 | 1; | |
1255 | ||
1256 | B<Test File> test.pl | |
1257 | ||
1258 | use warnings; | |
1259 | use strict; | |
1260 | use My::Schema; | |
1261 | ||
1262 | my $user_data = { email => 'someguy@place.com', | |
1263 | password => 'pass1', | |
1264 | admin => 0 }; | |
1265 | ||
1266 | my $admin_data = { email => 'someadmin@adminplace.com', | |
1267 | password => 'pass2', | |
1268 | admin => 1 }; | |
1269 | ||
1270 | my $schema = My::Schema->connection('dbi:Pg:dbname=test'); | |
1271 | ||
1272 | $schema->resultset('User')->create( $user_data ); | |
1273 | $schema->resultset('User')->create( $admin_data ); | |
1274 | ||
1275 | ### Now we search for them | |
1276 | my $user = $schema->resultset('User')->single( $user_data ); | |
1277 | my $admin = $schema->resultset('User')->single( $admin_data ); | |
1278 | ||
1279 | print ref $user, "\n"; | |
1280 | print ref $admin, "\n"; | |
1281 | ||
1282 | print $user->password , "\n"; # pass1 | |
1283 | print $admin->password , "\n";# pass2; inherited from User | |
1284 | print $user->hello , "\n";# I am a regular user. | |
1285 | print $admin->hello, "\n";# I am an admin. | |
1286 | ||
1287 | ### The statement below will NOT print | |
1288 | print "I can do admin stuff\n" if $user->can('do_admin_stuff'); | |
1289 | ### The statement below will print | |
1290 | print "I can do admin stuff\n" if $admin->can('do_admin_stuff'); | |
1291 | ||
1292 | Alternatively you can use L<DBIx::Class::DynamicSubclass> that implements | |
1293 | exactly the above functionality. | |
1294 | ||
1295 | =head2 高速に結果を得るために、オブジェクトの作成をスキップしたい | |
1296 | ||
1297 | =begin original | |
1298 | ||
1299 | DBIx::Class is not built for speed, it's built for convenience and | |
1300 | ease of use, but sometimes you just need to get the data, and skip the | |
1301 | fancy objects. | |
1302 | ||
1303 | =end original | |
1304 | ||
1305 | DBIx::Class はスピードのためには作られておらず、DBIx::Classは、 | |
1306 | 利便性と使い易さのために作られました。ですが、時には、データをただ | |
1307 | 取得しなければいけないだけの時があり、素敵なオブジェクトはスキップ | |
1308 | したい場合もあるでしょう。 | |
1309 | ||
1310 | To do this simply use L<DBIx::Class::ResultClass::HashRefInflator>. | |
1311 | ||
1312 | この用途には、L<DBIx::Class::ResultClass::HashRefInflator>が、簡単に使えます。 | |
1313 | ||
1314 | my $rs = $schema->resultset('CD'); | |
1315 | ||
1316 | $rs->result_class('DBIx::Class::ResultClass::HashRefInflator'); | |
1317 | ||
1318 | my $hash_ref = $rs->find(1); | |
1319 | ||
1320 | Wasn't that easy? | |
1321 | ||
1322 | Beware, changing the Result class using | |
1323 | L<DBIx::Class::ResultSet/result_class> will replace any existing class | |
1324 | completely including any special components loaded using | |
1325 | load_components, eg L<DBIx::Class::InflateColumn::DateTime>. | |
1326 | ||
1327 | =head2 Get raw data for blindingly fast results | |
1328 | ||
1329 | If the L<HashRefInflator|DBIx::Class::ResultClass::HashRefInflator> solution | |
1330 | above is not fast enough for you, you can use a DBIx::Class to return values | |
1331 | exactly as they come out of the database with none of the convenience methods | |
1332 | wrapped round them. | |
1333 | ||
1334 | This is used like so: | |
1335 | ||
1336 | my $cursor = $rs->cursor | |
1337 | while (my @vals = $cursor->next) { | |
1338 | # use $val[0..n] here | |
1339 | } | |
1340 | ||
1341 | You will need to map the array offsets to particular columns (you can | |
1342 | use the L<DBIx::Class::ResultSet/select> attribute of L<DBIx::Class::ResultSet/search> to force ordering). | |
1343 | ||
1344 | =head1 RESULTSET OPERATIONS | |
1345 | ||
1346 | =head2 Getting Schema from a ResultSet | |
1347 | ||
1348 | To get the L<DBIx::Class::Schema> object from a ResultSet, do the following: | |
1349 | ||
1350 | $rs->result_source->schema | |
1351 | ||
1352 | =head2 Getting Columns Of Data | |
1353 | ||
1354 | AKA Aggregating Data | |
1355 | ||
1356 | =begin original | |
1357 | ||
1358 | 536 | If you want to find the sum of a particular column there are several |
1359 | 537 | ways, the obvious one is to use search: |
1360 | 538 | |
1361 | =end original | |
1362 | ||
1363 | 539 | 特定のカラムの合計を探したければ、いくつもの方法があります。自明のものとしては、 |
1364 | 540 | searchを使うものです: |
1365 | 541 | |
1366 | 542 | my $rs = $schema->resultset('Items')->search( |
1367 | 543 | {}, |
1368 | { | |
544 | { | |
1369 | 545 | select => [ { sum => 'Cost' } ], |
1370 | 546 | as => [ 'total_cost' ], # remember this 'as' is for DBIx::Class::ResultSet not SQL |
1371 | 547 | } |
1372 | 548 | ); |
1373 | 549 | my $tc = $rs->first->get_column('total_cost'); |
1374 | 550 | |
1375 | =begin original | |
1376 | ||
1377 | 551 | Or, you can use the L<DBIx::Class::ResultSetColumn>, which gets |
1378 | 552 | returned when you ask the C<ResultSet> for a column using |
1379 | 553 | C<get_column>: |
1380 | 554 | |
1381 | =end original | |
1382 | ||
1383 | 555 | もしくは、L<DBIx::Class::ResultSetColumn>を使うことも出来ます。 |
1384 | 556 | これは、C<ResultSet>でC<get_column>を使ってカラムを取るときに |
1385 | 557 | 返されるものが取れます。 |
1386 | 558 | |
1387 | 559 | my $cost = $schema->resultset('Items')->get_column('Cost'); |
1388 | 560 | my $tc = $cost->sum; |
1389 | 561 | |
1390 | =begin original | |
1391 | ||
1392 | 562 | With this you can also do: |
1393 | 563 | |
1394 | =end original | |
1395 | ||
1396 | 564 | これを、次のようにできます: |
1397 | 565 | |
1398 | 566 | my $minvalue = $cost->min; |
1399 | 567 | my $maxvalue = $cost->max; |
1400 | 568 | |
1401 | =begin original | |
1402 | ||
1403 | 569 | Or just iterate through the values of this column only: |
1404 | 570 | |
1405 | =end original | |
1406 | ||
1407 | 571 | または、このカラムの値のみを通してイテレートします: |
1408 | 572 | |
1409 | 573 | while ( my $c = $cost->next ) { |
1410 | 574 | print $c; |
1411 | 575 | } |
1412 | 576 | |
1413 | 577 | foreach my $c ($cost->all) { |
1414 | 578 | print $c; |
1415 | 579 | } |
1416 | 580 | |
1417 | ||
581 | C<ResultSetColumn> only has a limited number of built-in functions, if | |
1418 | ||
1419 | C<ResultSetColumn> only has a limited number of built-in functions. If | |
1420 | 582 | you need one that it doesn't have, then you can use the C<func> method |
1421 | 583 | instead: |
1422 | 584 | |
1423 | =end original | |
1424 | ||
1425 | 585 | C<ResultSetColumn>は少しだけビルトインの関数があります。 |
1426 | 586 | これにないものが必要なら、C<func>メソッドを代わりに使うことができます: |
1427 | 587 | |
1428 | 588 | my $avg = $cost->func('AVERAGE'); |
1429 | 589 | |
1430 | =begin original | |
1431 | ||
1432 | 590 | This will cause the following SQL statement to be run: |
1433 | 591 | |
1434 | =end original | |
1435 | ||
1436 | 592 | こうすると、下記のSQLステートメントが走ります: |
1437 | 593 | |
1438 | 594 | SELECT AVERAGE(Cost) FROM Items me |
1439 | 595 | |
1440 | =begin original | |
1441 | ||
1442 | 596 | Which will of course only work if your database supports this function. |
1443 | 597 | See L<DBIx::Class::ResultSetColumn> for more documentation. |
1444 | 598 | |
1445 | =end original | |
1446 | ||
1447 | 599 | もちろん、使っているデータベースがこの関数をサポートしていなければいけません。 |
1448 | 600 | より詳しくは、L<DBIx::Class::ResultSetColumn>をみてください。 |
1449 | 601 | |
1450 | =head2 | |
602 | =head2 リレーションシップを使う | |
1451 | 603 | |
1452 | ||
604 | =head3 関連するテーブルに新しい列を作る | |
1453 | resultset without the need to hit the DB again. You can do that by using the | |
1454 | L<set_cache|DBIx::Class::Resultset/set_cache> method: | |
1455 | 605 | |
1456 | my | |
606 | my $book->create_related('author', { name => 'Fred'}); | |
1457 | while (my $group = $groups->next) { | |
1458 | if ($group->can_upload($self)) { | |
1459 | push @uploadable_groups, $group; | |
1460 | } | |
1461 | } | |
1462 | my $new_rs = $self->result_source->resultset; | |
1463 | $new_rs->set_cache(\@uploadable_groups); | |
1464 | return $new_rs; | |
1465 | 607 | |
1466 | =head | |
608 | =head3 関連するテーブルを検索する | |
1467 | 609 | |
1468 | =head2 関連するテーブルに新しい列を作る | |
1469 | ||
1470 | my $author = $book->create_related('author', { name => 'Fred'}); | |
1471 | ||
1472 | =head2 関連するテーブルを検索する | |
1473 | ||
1474 | =begin original | |
1475 | ||
1476 | 610 | Only searches for books named 'Titanic' by the author in $author. |
1477 | 611 | |
1478 | =end original | |
1479 | ||
1480 | 612 | $autorの著者で、'Titanic'という名前の本だけを検索したい。 |
1481 | 613 | |
1482 | my $ | |
614 | my $author->search_related('books', { name => 'Titanic' }); | |
1483 | 615 | |
1484 | =head | |
616 | =head3 関連するテーブルのデータを削除する | |
1485 | 617 | |
1486 | =begin original | |
1487 | ||
1488 | 618 | Deletes only the book named Titanic by the author in $author. |
1489 | 619 | |
1490 | =end original | |
1491 | ||
1492 | 620 | $autorの著者で、Titanicという名前の本だけを削除したい。 |
1493 | 621 | |
1494 | $author->delete_related('books', { name => 'Titanic' }); | |
622 | my $author->delete_related('books', { name => 'Titanic' }); | |
1495 | 623 | |
1496 | =head | |
624 | =head3 関係する結果セットの順序付け | |
1497 | 625 | |
1498 | ||
626 | If you always want a relation to be ordered, you can specify this when you | |
1499 | ||
1500 | If you always want a relation to be ordered, you can specify this when you | |
1501 | 627 | create the relationship. |
1502 | 628 | |
1503 | =end original | |
1504 | ||
1505 | 629 | 順序付けられた関係が常にほしいなら、リレーションシップを作るときに、次の指定をできます。 |
1506 | 630 | |
1507 | ||
631 | To order C<< $book->pages >> by descending page_number. | |
1508 | 632 | |
1509 | ||
633 | page_numberを降順で、C<< $book->pages >>を並び変えたいなら。 | |
1510 | as follows: | |
1511 | 634 | |
1512 | =e | |
635 | Book->has_many('pages' => 'Page', 'book', { order_by => \'page_number DESC'} ); | |
1513 | 636 | |
1514 | ||
637 | =head2 トランザクション | |
1515 | リレーションを作ります: | |
1516 | 638 | |
1517 | ||
1518 | __PACKAGE__->has_many('pages' => 'Page', 'book', { order_by => { -desc => 'page_number'} } ); | |
1519 | ||
1520 | =head2 Filtering a relationship result set | |
1521 | ||
1522 | If you want to get a filtered result set, you can just add add to $attr as follows: | |
1523 | ||
1524 | __PACKAGE__->has_many('pages' => 'Page', 'book', { where => { scrap => 0 } } ); | |
1525 | ||
1526 | =head2 Many-to-many のリレーションシップ | |
1527 | ||
1528 | =begin original | |
1529 | ||
1530 | This is straightforward using L<ManyToMany|DBIx::Class::Relationship/many_to_many>: | |
1531 | ||
1532 | =end original | |
1533 | ||
1534 | これは、単純にL<ManyToMany|DBIx::Class::Relationship/many_to_many>を使います: | |
1535 | ||
1536 | package My::User; | |
1537 | use base 'DBIx::Class::Core'; | |
1538 | __PACKAGE__->table('user'); | |
1539 | __PACKAGE__->add_columns(qw/id name/); | |
1540 | __PACKAGE__->set_primary_key('id'); | |
1541 | __PACKAGE__->has_many('user_address' => 'My::UserAddress', 'user'); | |
1542 | __PACKAGE__->many_to_many('addresses' => 'user_address', 'address'); | |
1543 | ||
1544 | package My::UserAddress; | |
1545 | use base 'DBIx::Class::Core'; | |
1546 | __PACKAGE__->table('user_address'); | |
1547 | __PACKAGE__->add_columns(qw/user address/); | |
1548 | __PACKAGE__->set_primary_key(qw/user address/); | |
1549 | __PACKAGE__->belongs_to('user' => 'My::User'); | |
1550 | __PACKAGE__->belongs_to('address' => 'My::Address'); | |
1551 | ||
1552 | package My::Address; | |
1553 | use base 'DBIx::Class::Core'; | |
1554 | __PACKAGE__->table('address'); | |
1555 | __PACKAGE__->add_columns(qw/id street town area_code country/); | |
1556 | __PACKAGE__->set_primary_key('id'); | |
1557 | __PACKAGE__->has_many('user_address' => 'My::UserAddress', 'address'); | |
1558 | __PACKAGE__->many_to_many('users' => 'user_address', 'user'); | |
1559 | ||
1560 | $rs = $user->addresses(); # get all addresses for a user | |
1561 | $rs = $address->users(); # get all users for an address | |
1562 | ||
1563 | my $address = $user->add_to_addresses( # returns a My::Address instance, | |
1564 | # NOT a My::UserAddress instance! | |
1565 | { | |
1566 | country => 'United Kingdom', | |
1567 | area_code => 'XYZ', | |
1568 | town => 'London', | |
1569 | street => 'Sesame', | |
1570 | } | |
1571 | ); | |
1572 | ||
1573 | =head2 Relationships across DB schemas | |
1574 | ||
1575 | Mapping relationships across L<DB schemas|DBIx::Class::Manual::Glossary/DB schema> | |
1576 | is easy as long as the schemas themselves are all accessible via the same DBI | |
1577 | connection. In most cases, this means that they are on the same database host | |
1578 | as each other and your connecting database user has the proper permissions to them. | |
1579 | ||
1580 | To accomplish this one only needs to specify the DB schema name in the table | |
1581 | declaration, like so... | |
1582 | ||
1583 | package MyDatabase::Main::Artist; | |
1584 | use base qw/DBIx::Class::Core/; | |
1585 | ||
1586 | __PACKAGE__->table('database1.artist'); # will use "database1.artist" in FROM clause | |
1587 | ||
1588 | __PACKAGE__->add_columns(qw/ artist_id name /); | |
1589 | __PACKAGE__->set_primary_key('artist_id'); | |
1590 | __PACKAGE__->has_many('cds' => 'MyDatabase::Main::Cd'); | |
1591 | ||
1592 | 1; | |
1593 | ||
1594 | Whatever string you specify there will be used to build the "FROM" clause in SQL | |
1595 | queries. | |
1596 | ||
1597 | The big drawback to this is you now have DB schema names hardcoded in your | |
1598 | class files. This becomes especially troublesome if you have multiple instances | |
1599 | of your application to support a change lifecycle (e.g. DEV, TEST, PROD) and | |
1600 | the DB schemas are named based on the environment (e.g. database1_dev). | |
1601 | ||
1602 | However, one can dynamically "map" to the proper DB schema by overriding the | |
1603 | L<connection|DBIx::Class::Schama/connection> method in your Schema class and | |
1604 | building a renaming facility, like so: | |
1605 | ||
1606 | package MyDatabase::Schema; | |
1607 | use Moose; | |
1608 | ||
1609 | extends 'DBIx::Class::Schema'; | |
1610 | ||
1611 | around connection => sub { | |
1612 | my ( $inner, $self, $dsn, $username, $pass, $attr ) = ( shift, @_ ); | |
1613 | ||
1614 | my $postfix = delete $attr->{schema_name_postfix}; | |
1615 | ||
1616 | $inner->(@_); | |
1617 | ||
1618 | if ( $postfix ) { | |
1619 | $self->append_db_name($postfix); | |
1620 | } | |
1621 | }; | |
1622 | ||
1623 | sub append_db_name { | |
1624 | my ( $self, $postfix ) = @_; | |
1625 | ||
1626 | my @sources_with_db | |
1627 | = grep | |
1628 | { $_->name =~ /^\w+\./mx } | |
1629 | map | |
1630 | { $self->source($_) } | |
1631 | $self->sources; | |
1632 | ||
1633 | foreach my $source (@sources_with_db) { | |
1634 | my $name = $source->name; | |
1635 | $name =~ s{^(\w+)\.}{${1}${postfix}\.}mx; | |
1636 | ||
1637 | $source->name($name); | |
1638 | } | |
1639 | } | |
1640 | ||
1641 | 1; | |
1642 | ||
1643 | By overridding the L<connection|DBIx::Class::Schama/connection> | |
1644 | method and extracting a custom option from the provided \%attr hashref one can | |
1645 | then simply iterate over all the Schema's ResultSources, renaming them as | |
1646 | needed. | |
1647 | ||
1648 | To use this facility, simply add or modify the \%attr hashref that is passed to | |
1649 | L<connection|DBIx::Class::Schama/connect>, as follows: | |
1650 | ||
1651 | my $schema | |
1652 | = MyDatabase::Schema->connect( | |
1653 | $dsn, | |
1654 | $user, | |
1655 | $pass, | |
1656 | { | |
1657 | schema_name_postfix => '_dev' | |
1658 | # ... Other options as desired ... | |
1659 | }) | |
1660 | ||
1661 | Obviously, one could accomplish even more advanced mapping via a hash map or a | |
1662 | callback routine. | |
1663 | ||
1664 | =head1 txn_do でのトランザクション | |
1665 | ||
1666 | 639 | As of version 0.04001, there is improved transaction support in |
1667 | L<DBIx::Class::Storage> and L<DBIx::Class::Schema>. Here is an | |
640 | L<DBIx::Class::Storage::DBI> and L<DBIx::Class::Schema>. Here is an | |
1668 | 641 | example of the recommended way to use it: |
1669 | 642 | |
1670 | 643 | 0.04001以降に、 L<DBIx::Class::Storage::DBI>とL<DBIx::Class::Schema>に、改良された |
1671 | 644 | トランザクションサポートがあります。これを使う推奨される方法の一例です: |
1672 | 645 | |
1673 | 646 | my $genus = $schema->resultset('Genus')->find(12); |
1674 | 647 | |
1675 | 648 | my $coderef2 = sub { |
1676 | 649 | $genus->extinct(1); |
1677 | 650 | $genus->update; |
1678 | 651 | }; |
1679 | 652 | |
1680 | 653 | my $coderef1 = sub { |
1681 | 654 | $genus->add_to_species({ name => 'troglodyte' }); |
1682 | 655 | $genus->wings(2); |
1683 | 656 | $genus->update; |
1684 | $schema->txn_do($coderef2); # Can have a nested transaction | |
657 | $schema->txn_do($coderef2); # Can have a nested transaction | |
1685 | 658 | return $genus->species; |
1686 | 659 | }; |
1687 | 660 | |
1688 | use Try::Tiny; | |
1689 | 661 | my $rs; |
1690 | | |
662 | eval { | |
1691 | 663 | $rs = $schema->txn_do($coderef1); |
1692 | } | |
664 | }; | |
1693 | ||
666 | if ($@) { # Transaction failed | |
1694 | 667 | die "the sky is falling!" # |
1695 | if ($ | |
668 | if ($@ =~ /Rollback failed/); # Rollback failed | |
1696 | 669 | |
1697 | 670 | deal_with_failed_transaction(); |
1698 | } | |
671 | } | |
1699 | 672 | |
1700 | Note: by default C<txn_do> will re-run the coderef one more time if an | |
1701 | error occurs due to client disconnection (e.g. the server is bounced). | |
1702 | You need to make sure that your coderef can be invoked multiple times | |
1703 | without terrible side effects. | |
1704 | ||
1705 | =begin original | |
1706 | ||
1707 | 673 | Nested transactions will work as expected. That is, only the outermost |
1708 | 674 | transaction will actually issue a commit to the $dbh, and a rollback |
1709 | 675 | at any level of any transaction will cause the entire nested |
1710 | transaction to fail. | |
676 | transaction to fail. Support for savepoints and for true nested | |
677 | transactions (for databases that support them) will hopefully be added | |
678 | in the future. | |
1711 | 679 | |
1712 | =end original | |
1713 | ||
1714 | 680 | ネストされたトランザクションは期待どおりに動きます。 |
1715 | 681 | 一番外側のトランザクションだけが実際に$dbhにコミットを発行します。 |
1716 | 682 | どのレベルのどのトランザクションでも、ロールバックしたら、 |
1717 | 683 | ネストされたトランザクション全てが失敗します。 |
684 | セーブポイントと、本当にネストされたトランザクション | |
685 | (それをサポートしているデータベース用に)は、将来、うまくいけば、追加されるでしょう。 | |
1718 | 686 | |
1719 | =head2 | |
687 | =head2 Many-to-many のリレーションシップ | |
1720 | 688 | |
1721 | ||
689 | This is straightforward using L<ManyToMany|DBIx::Class::Relationship/many_to_many>: | |
1722 | n | |
690 | これは、単純にL<ManyToMany|DBIx::Class::Relationship/many_to_many>を使います: | |
1723 | transactions, supply the C<< auto_savepoint = 1 >> connection attribute. | |
1724 | 691 | |
1725 | ||
692 | package My::DB; | |
1726 | ||
693 | # ... set up connection ... | |
1727 | fragile operation and might fail. If we fail creating something, depending on | |
1728 | the type of failure, we want to abort the whole task, or only skip the failed | |
1729 | row. | |
1730 | 694 | |
1731 | | |
695 | package My::User; | |
696 | use base 'My::DB'; | |
697 | __PACKAGE__->table('user'); | |
698 | __PACKAGE__->add_columns(qw/id name/); | |
699 | __PACKAGE__->set_primary_key('id'); | |
700 | __PACKAGE__->has_many('user_address' => 'My::UserAddress', 'user'); | |
701 | __PACKAGE__->many_to_many('addresses' => 'user_address', 'address'); | |
1732 | 702 | |
1733 | | |
703 | package My::UserAddress; | |
1734 | | |
704 | use base 'My::DB'; | |
1735 | use | |
705 | __PACKAGE__->table('user_address'); | |
1736 | | |
706 | __PACKAGE__->add_columns(qw/user address/); | |
1737 | try | |
707 | __PACKAGE__->set_primary_key(qw/user address/); | |
1738 | | |
708 | __PACKAGE__->belongs_to('user' => 'My::User'); | |
1739 | | |
709 | __PACKAGE__->belongs_to('address' => 'My::Address'); | |
1740 | 710 | |
1741 | | |
711 | package My::Address; | |
1742 | | |
712 | use base 'My::DB'; | |
713 | __PACKAGE__->table('address'); | |
714 | __PACKAGE__->add_columns(qw/id street town area_code country/); | |
715 | __PACKAGE__->set_primary_key('id'); | |
716 | __PACKAGE__->has_many('user_address' => 'My::UserAddress', 'address'); | |
717 | __PACKAGE__->many_to_many('users' => 'user_address', 'user'); | |
1743 | 718 | |
1744 | for | |
719 | $rs = $user->addresses(); # get all addresses for a user | |
720 | $rs = $address->users(); # get all users for an address | |
1745 | 721 | |
1746 | ||
722 | =head2 列のデフォルトの値を用意する | |
1747 | try { | |
1748 | $schema->txn_do(sub { | |
1749 | # SQL: SAVEPOINT savepoint_0; | |
1750 | 723 | |
1751 | | |
724 | It's as simple as overriding the C<new> method. Note the use of | |
1752 | ||
725 | C<next::method>. | |
1753 | 726 | |
1754 | ||
727 | 単純に、C<new>メソッドをオーバーライドします。 | |
1755 | ||
728 | C<next::method>の使いかたに注意してください。 | |
1756 | 729 | |
1757 | | |
730 | sub new { | |
1758 | | |
731 | my ( $self, $attrs ) = @_; | |
1759 | # WHERE ( id = 42 ); | |
1760 | } | |
1761 | }); | |
1762 | } catch { | |
1763 | # SQL: ROLLBACK TO SAVEPOINT savepoint_0; | |
1764 | 732 | |
1765 | | |
733 | $attrs->{foo} = 'bar' unless defined $attrs->{foo}; | |
1766 | # we want to abort the whole transaction, or only rollback the | |
1767 | # changes related to the creation of this $thing | |
1768 | 734 | |
1769 | | |
735 | $self->next::method($attrs); | |
1770 | if ($_ =~ /horrible_problem/) { | |
1771 | print "something horrible happend, aborting job!"; | |
1772 | die $_; # rethrow error | |
1773 | } | |
1774 | 736 | |
1775 | | |
737 | return $self; | |
1776 | # next $thing | |
1777 | print "Cannot create thing: $_"; | |
1778 | } | |
1779 | # There was no error, so save all changes since the last | |
1780 | # savepoint. | |
1781 | ||
1782 | # SQL: RELEASE SAVEPOINT savepoint_0; | |
1783 | } | |
1784 | }); | |
1785 | } catch { | |
1786 | $exception = $_; | |
1787 | 738 | } |
1788 | 739 | |
1789 | if | |
740 | For more information about C<next::method>, look in the L<Class::C3> | |
1790 | | |
741 | documentation. See also L<DBIx::Class::Manual::Component> for more | |
1791 | | |
742 | ways to write your own base classes to do this. | |
1792 | # ('released') savepoints. There will be neither a new $job nor any | |
1793 | # $thing entry in the database. | |
1794 | 743 | |
1795 | ||
744 | C<next::method>についてより詳しくは、L<Class::C3>のドキュメントを参照してください。 | |
745 | これをするための、自分自身のベースクラスを書くための、より多くの方法については、 | |
746 | L<DBIx::CLass::Manual::Component>を見てください。 | |
1796 | 747 | |
1797 | | |
748 | People looking for ways to do "triggers" with DBIx::Class are probably | |
1798 | | |
749 | just looking for this. | |
1799 | else { | |
1800 | # There was no error while handling the $job. Commit all changes. | |
1801 | # Only now other connections can see the newly created $job and | |
1802 | # @things. | |
1803 | 750 | |
1804 | ||
751 | DBIx::Classで"triggers"をする方法を探している人も、これを探しているでしょう。 | |
1805 | 752 | |
1806 | | |
753 | =head2 Stringification | |
1807 | } | |
1808 | 754 | |
1809 | ||
755 | Employ the standard stringification technique by using the C<overload> | |
1810 | ||
756 | module. | |
1811 | the C<try>-block around C<txn_do> fails, a rollback is issued. If the C<try> | |
1812 | succeeds, the transaction is committed (or the savepoint released). | |
1813 | 757 | |
1814 | ||
758 | C<overload> モジュールで標準的な文字列化のテクニックを使えます。 | |
1815 | and C<svp_rollback>, it is strongly recommended to use C<txn_do> with coderefs. | |
1816 | 759 | |
1817 | ||
760 | To make an object stringify itself as a single column, use something | |
761 | like this (replace C<foo> with the column/method of your choice): | |
1818 | 762 | |
1819 | ||
763 | ひとつのカラムについて、オブジェクト自身を文字列化するには、 | |
1820 | ||
764 | 次のようにします。(カラム/メソッドでC<foo>を置き換えてください) | |
1821 | related objects> for an example. | |
1822 | 765 | |
1823 | ||
766 | use overload '""' => sub { shift->name}, fallback => 1; | |
1824 | alive when issuing the C<BEGIN> statement. It will not (and really can not) | |
1825 | retry if the server goes away mid-operations, unlike C<txn_do>. | |
1826 | 767 | |
1827 | ||
768 | For more complex stringification, you can use an anonymous subroutine: | |
1828 | 769 | |
1829 | ||
770 | より複雑な文字列化では、無名サブルーチンを使えます: | |
1830 | 771 | |
1831 | ||
772 | use overload '""' => sub { $_[0]->name . ", " . | |
1832 | ||
773 | $_[0]->address }, fallback => 1; | |
1833 | 774 | |
1834 | ||
775 | =head3 文字列化の例 | |
1835 | L<make_schema_at|DBIx::Class::Schema::Loader/make_schema_at> method: | |
1836 | 776 | |
1837 | ||
777 | Suppose we have two tables: C<Product> and C<Category>. The table | |
1838 | ||
778 | specifications are: | |
1839 | 779 | |
1840 | ||
780 | 二つのテーブルがあるとします:C<Product>とC<Cateogry>。 | |
1841 | ||
781 | テーブルの定義は次の通り: | |
1842 | 782 | |
1843 | ||
783 | Product(id, Description, category) | |
784 | Category(id, Description) | |
1844 | 785 | |
1845 | ||
786 | C<category> is a foreign key into the Category table. | |
1846 | (also known as "SQL Fairy") installed. | |
1847 | 787 | |
1848 | ||
788 | C<category>はCategoryテーブルの外部キーです。 | |
1849 | 789 | |
1850 | | |
790 | If you have a Product object C<$obj> and write something like | |
1851 | $schema->create_ddl_dir(['MySQL', 'SQLite', 'PostgreSQL'], | |
1852 | '0.1', | |
1853 | './dbscriptdir/' | |
1854 | ); | |
1855 | 791 | |
1856 | ||
792 | ProductオブジェクトC<$obj>があり、次のように書いたとすると、 | |
1857 | MySQL, SQLite and PostgreSQL, using the $VERSION from your Schema.pm. | |
1858 | 793 | |
1859 | ||
794 | print $obj->category | |
1860 | 795 | |
1861 | | |
796 | things will not work as expected. | |
1862 | $schema->deploy({ add_drop_table => 1}); | |
1863 | 797 | |
1864 | ||
798 | 期待どおりには動きません。 | |
1865 | 799 | |
1866 | m | |
800 | To obtain, for example, the category description, you should add this | |
801 | method to the class defining the Category table: | |
1867 | 802 | |
1868 | ||
803 | カテゴリの内容を得たいなら、例えば、Categoryテーブルのクラス定義に次の | |
1869 | ||
804 | メソッドを追加すべきです: | |
1870 | C<$VERSION> in your Schema file, then: | |
1871 | 805 | |
1872 | | |
806 | use overload "" => sub { | |
1873 | $s | |
807 | my $self = shift; | |
1874 | '0.2', | |
1875 | '/dbscriptdir/', | |
1876 | '0.1' | |
1877 | ); | |
1878 | 808 | |
1879 | ||
809 | return $self->Description; | |
1880 | ||
810 | }, fallback => 1; | |
1881 | requires that the files for 0.1 as created above are available in the | |
1882 | given directory to diff against. | |
1883 | 811 | |
1884 | =head2 | |
812 | =head2 きれいに切断 | |
1885 | 813 | |
1886 | ||
814 | If you find yourself quitting an app with Control-C a lot during | |
1887 | ||
815 | development, you might like to put the following signal handler in | |
1888 | ||
816 | your main database class to make sure it disconnects cleanly: | |
1889 | L<http://troels.arvin.dk/db/rdbms/#other-dummy_table>. | |
1890 | 817 | |
1891 | ||
818 | 開発中に、Cotrol-Cを多用して、アプリケーションを終了させることが | |
1892 | ||
819 | 多いなら、下記のようなシグナルハンドラーをデータベースクラスに置いて、 | |
1893 | ||
820 | 確実にきれいに切断したいかもしれません: | |
1894 | 821 | |
1895 | ||
822 | $SIG{INT} = sub { | |
823 | __PACKAGE__->storage->disconnect; | |
824 | }; | |
1896 | 825 | |
1897 | ||
826 | =head2 スキーマのインポート/エクスポート | |
1898 | use strict; | |
1899 | use warnings; | |
1900 | use base 'DBIx::Class::Core'; | |
1901 | __PACKAGE__->table("Dual"); | |
1902 | __PACKAGE__->add_columns( | |
1903 | "dummy", | |
1904 | { data_type => "VARCHAR2", is_nullable => 0, size => 1 }, | |
1905 | ); | |
1906 | 827 | |
1907 | ||
828 | This functionality requires you to have L<SQL::Translator> (also known as | |
1908 | ||
829 | "SQL Fairy") installed. | |
1909 | 830 | |
1910 | ||
831 | この機能を使うには、L<SQL::Translator>("SQL Fairy"とも知られる)を | |
1911 | ||
832 | インストールする必要があります。 | |
1912 | as => [ 'now' ] | |
1913 | }, | |
1914 | ); | |
1915 | 833 | |
1916 | ||
834 | To create a DBIx::Class schema from an existing database: | |
1917 | will not work because there is no column called 'now' in the Dual table class | |
1918 | 835 | |
1919 | ||
836 | DBIx::Classスキーマを既存のデータベースから作ります: | |
1920 | print $dual->now."\n"; | |
1921 | } | |
1922 | # Can't locate object method "now" via package "MyAppDB::Dual" at headshot.pl line 23. | |
1923 | 837 | |
1924 | ||
838 | sqlt --from DBI | |
1925 | ||
839 | --to DBIx::Class::File | |
1926 | ||
840 | --prefix "MySchema" > MySchema.pm | |
1927 | 841 | |
1928 | | |
842 | To create a MySQL database from an existing L<DBIx::Class> schema, convert the | |
1929 | | |
843 | schema to MySQL's dialect of SQL: | |
1930 | } | |
1931 | 844 | |
1932 | ||
845 | MySQLデータベースを既存のL<DBIx::Class>スキーマから作ります。 | |
846 | スキーマをMySQLのSQL方言に変換します: | |
1933 | 847 | |
1934 | m | |
848 | sqlt --from SQL::Translator::Parser::DBIx::Class | |
1935 | | |
849 | --to MySQL | |
1936 | | |
850 | --DBIx::Class "MySchema.pm" > Schema1.sql | |
1937 | | |
851 | ||
852 | And import using the mysql client: | |
1938 | 853 | |
1939 | ||
854 | mysqlクライアントでimportします: | |
1940 | L<DBIx::Class::Schema/create_ddl_dir> a table called "dual" will be created in your | |
1941 | current schema. This would overlap "sys.dual" and you could not fetch "sysdate" or | |
1942 | "sequence.nextval" anymore from dual. To avoid this problem, just tell | |
1943 | L<SQL::Translator> to not create table dual: | |
1944 | 855 | |
1945 | | |
856 | mysql -h "host" -D "database" -u "user" -p < Schema1.sql | |
1946 | add_drop_table => 1, | |
1947 | parser_args => { sources => [ grep $_ ne 'Dual', schema->sources ] }, | |
1948 | }; | |
1949 | $schema->create_ddl_dir( [qw/Oracle/], undef, './sql', undef, $sqlt_args ); | |
1950 | 857 | |
1951 | ||
858 | =head2 クラスベースからスキーマベースセットアップへの簡単な移行 | |
1952 | 859 | |
1953 | | |
860 | You want to start using the schema-based approach to L<DBIx::Class> | |
1954 | | |
861 | (see L<SchemaIntro.pod>), but have an established class-based setup with lots | |
1955 | | |
862 | of existing classes that you don't want to move by hand. Try this nifty script | |
1956 | ||
863 | instead: | |
1957 | 864 | |
1958 | ||
865 | L<DBIx::Class>へのスキーマベースのアプローチを使いたい(L<SchemaIntro.pod>をみてください)、 | |
1959 | ||
866 | でも、既存の大量のクラスで、従来のクラスベースのセットアップがあり、 | |
1960 | ||
867 | 手でそれらを動かしたくはないとします。手で動かす変わりに、下記の気の利いたスクリプトを | |
868 | 試してみて下さい: | |
1961 | 869 | |
1962 | # get a sequence value | |
1963 | select => [ 'A_SEQ.nextval' ], | |
1964 | 870 | |
1965 | | |
871 | use MyDB; | |
1966 | se | |
872 | use SQL::Translator; | |
873 | ||
874 | my $schema = MyDB->schema_instance; | |
875 | ||
876 | my $translator = SQL::Translator->new( | |
877 | debug => $debug || 0, | |
878 | trace => $trace || 0, | |
879 | no_comments => $no_comments || 0, | |
880 | show_warnings => $show_warnings || 0, | |
881 | add_drop_table => $add_drop_table || 0, | |
882 | validate => $validate || 0, | |
883 | parser_args => { | |
884 | 'DBIx::Schema' => $schema, | |
885 | }, | |
886 | producer_args => { | |
887 | 'prefix' => 'My::Schema', | |
888 | }, | |
889 | ); | |
890 | ||
891 | $translator->parser('SQL::Translator::Parser::DBIx::Class'); | |
892 | $translator->producer('SQL::Translator::Producer::DBIx::Class::File'); | |
893 | ||
894 | my $output = $translator->translate(@args) or die | |
895 | "Error: " . $translator->error; | |
896 | ||
897 | print $output; | |
1967 | 898 | |
1968 | | |
899 | You could use L<Module::Find> to search for all subclasses in the MyDB::* | |
1969 | sele | |
900 | namespace, which is currently left as an exercise for the reader. | |
1970 | 901 | |
1971 | ||
902 | L<Module::Find>を使って、MyDB::*名前空間にある全てのサブクラスを探すことが出来ますが、 | |
1972 | ||
903 | これは、今のところ、読者への課題としておきます。 | |
1973 | 904 | |
1974 | # do some math | |
1975 | select => [ {'round' => [{'cos' => [ \'180 * 3.14159265359/180' ]}]}], | |
1976 | 905 | |
1977 | # which day of the week were you born on? | |
1978 | select => [{'to_char' => [{'to_date' => [ "'25-DEC-1980'", "'dd-mon-yyyy'" ]}, "'day'"]}], | |
1979 | ||
1980 | # select 16 rows from dual | |
1981 | select => [ "'hello'" ], | |
1982 | as => [ 'world' ], | |
1983 | group_by => [ 'cube( 1, 2, 3, 4 )' ], | |
1984 | ||
1985 | ||
1986 | ||
1987 | =head2 Adding Indexes And Functions To Your SQL | |
1988 | ||
1989 | Often you will want indexes on columns on your table to speed up searching. To | |
1990 | do this, create a method called C<sqlt_deploy_hook> in the relevant source | |
1991 | class (refer to the advanced | |
1992 | L<callback system|DBIx::Class::ResultSource/sqlt_deploy_callback> if you wish | |
1993 | to share a hook between multiple sources): | |
1994 | ||
1995 | package My::Schema::Result::Artist; | |
1996 | ||
1997 | __PACKAGE__->table('artist'); | |
1998 | __PACKAGE__->add_columns(id => { ... }, name => { ... }) | |
1999 | ||
2000 | sub sqlt_deploy_hook { | |
2001 | my ($self, $sqlt_table) = @_; | |
2002 | ||
2003 | $sqlt_table->add_index(name => 'idx_name', fields => ['name']); | |
2004 | } | |
2005 | ||
2006 | 1; | |
2007 | ||
2008 | Sometimes you might want to change the index depending on the type of the | |
2009 | database for which SQL is being generated: | |
2010 | ||
2011 | my ($db_type = $sqlt_table->schema->translator->producer_type) | |
2012 | =~ s/^SQL::Translator::Producer:://; | |
2013 | ||
2014 | You can also add hooks to the schema level to stop certain tables being | |
2015 | created: | |
2016 | ||
2017 | package My::Schema; | |
2018 | ||
2019 | ... | |
2020 | ||
2021 | sub sqlt_deploy_hook { | |
2022 | my ($self, $sqlt_schema) = @_; | |
2023 | ||
2024 | $sqlt_schema->drop_table('table_name'); | |
2025 | } | |
2026 | ||
2027 | You could also add views, procedures or triggers to the output using | |
2028 | L<SQL::Translator::Schema/add_view>, | |
2029 | L<SQL::Translator::Schema/add_procedure> or | |
2030 | L<SQL::Translator::Schema/add_trigger>. | |
2031 | ||
2032 | ||
2033 | 906 | =head2 スキーマのバージョニング |
2034 | 907 | |
2035 | =begin original | |
2036 | ||
2037 | 908 | The following example shows simplistically how you might use DBIx::Class to |
2038 | 909 | deploy versioned schemas to your customers. The basic process is as follows: |
2039 | 910 | |
2040 | =end original | |
2041 | ||
2042 | 911 | 下記の例では、DBIx::Classを使って、顧客向けにバージョン付きのスキーマをどうやって |
2043 | 912 | デプロイするかをお見せします。基本的なプロセスは下記のようになります: |
2044 | 913 | |
2045 | 914 | =over 4 |
2046 | 915 | |
2047 | 916 | =item 1. |
2048 | 917 | |
2049 | =begin original | |
2050 | ||
2051 | 918 | Create a DBIx::Class schema |
2052 | 919 | |
2053 | =end original | |
2054 | ||
2055 | 920 | DBIx::Classスキーマを作ります |
2056 | 921 | |
2057 | 922 | =item 2. |
2058 | 923 | |
2059 | =begin original | |
2060 | ||
2061 | 924 | Save the schema |
2062 | 925 | |
2063 | =end original | |
2064 | ||
2065 | 926 | スキーマを保存します |
2066 | 927 | |
2067 | 928 | =item 3. |
2068 | 929 | |
2069 | =begin original | |
2070 | ||
2071 | 930 | Deploy to customers |
2072 | 931 | |
2073 | =end original | |
2074 | ||
2075 | 932 | 顧客にデプロイします |
2076 | 933 | |
2077 | 934 | =item 4. |
2078 | 935 | |
2079 | =begin original | |
2080 | ||
2081 | 936 | Modify schema to change functionality |
2082 | 937 | |
2083 | =end original | |
2084 | ||
2085 | 938 | スキーマを変更して、 functionality を変更します |
2086 | 939 | |
2087 | 940 | =item 5. |
2088 | 941 | |
2089 | =begin original | |
2090 | ||
2091 | 942 | Deploy update to customers |
2092 | 943 | |
2093 | =end original | |
2094 | ||
2095 | 944 | 顧客に更新をデプロイします |
2096 | 945 | |
2097 | 946 | =back |
2098 | 947 | |
2099 | = | |
948 | =head3 DBIx::Calssスキーマを作る | |
2100 | 949 | |
2101 | B<Create a DBIx::Class schema> | |
2102 | ||
2103 | =end original | |
2104 | ||
2105 | B<DBIx::Calssスキーマを作る> | |
2106 | ||
2107 | =begin original | |
2108 | ||
2109 | 950 | This can either be done manually, or generated from an existing database as |
2110 | described under | |
951 | described under C<Schema import/export>. | |
2111 | 952 | |
2112 | ||
953 | これは、手で行うことも、C<Schema import/export>で説明しますが、 | |
2113 | ||
2114 | これは、手で行うことも、C<既存のデータベースからスキーマを作る>で説明しますが、 | |
2115 | 954 | 既存のデータベースから生成することもできます。 |
2116 | 955 | |
2117 | = | |
956 | =head3 スキーマを保存する | |
2118 | 957 | |
2119 | ||
958 | Use C<sqlt> to transform your schema into an SQL script suitable for your | |
959 | customer's database. E.g. for MySQL: | |
2120 | 960 | |
2121 | ||
961 | C<sqlt>を使って、スキーマを変換して、顧客のデータベース(例えば、MySQL)に合った、 | |
962 | SQLスクリプトにします。 | |
2122 | 963 | |
2123 | B | |
964 | sqlt --from SQL::Translator::Parser::DBIx::Class | |
965 | --to MySQL | |
966 | --DBIx::Class "MySchema.pm" > Schema1.mysql.sql | |
2124 | 967 | |
2125 | ||
968 | If you need to target databases from multiple vendors, just generate an SQL | |
969 | script suitable for each. To support PostgreSQL too: | |
2126 | 970 | |
2127 | ||
971 | 複数のベンダからデーベースをターゲットにしなければならないなら、 | |
972 | それぞれに合ったSQLスクリプトを生成するだけです。PostgreSQLもサポートしています: | |
2128 | 973 | |
2129 | ||
974 | sqlt --from SQL::Translator::DBIx::Class | |
975 | --to PostgreSQL | |
976 | --DBIx::Class "MySchema.pm" > Schema1.pgsql.sql | |
2130 | 977 | |
2131 | =e | |
978 | =head3 顧客にデプロイする | |
2132 | 979 | |
2133 | B<顧客にデプロイする> | |
2134 | ||
2135 | =begin original | |
2136 | ||
2137 | 980 | There are several ways you could deploy your schema. These are probably |
2138 | 981 | beyond the scope of this recipe, but might include: |
2139 | 982 | |
2140 | =end original | |
2141 | ||
2142 | 983 | スキーマをデプロイするのには複数の方法があります。 |
2143 | 984 | このレシピの範疇を越えそうですが、含めておきます: |
2144 | 985 | |
2145 | 986 | =over 4 |
2146 | 987 | |
2147 | 988 | =item 1. |
2148 | 989 | |
2149 | =begin original | |
2150 | ||
2151 | 990 | Require customer to apply manually using their RDBMS. |
2152 | 991 | |
2153 | =end original | |
2154 | ||
2155 | 992 | 顧客にRDBMSを使って、手で適用するように求める |
2156 | 993 | |
2157 | 994 | =item 2. |
2158 | 995 | |
2159 | =begin original | |
2160 | ||
2161 | 996 | Package along with your app, making database dump/schema update/tests |
2162 | 997 | all part of your install. |
2163 | 998 | |
2164 | =end original | |
2165 | ||
2166 | 999 | アプリケーションと一緒に、データベースのダンプ、スキーマのアップデート、 |
2167 | 1000 | インストールの全パートのテストを作るように、パッケージする |
2168 | 1001 | |
2169 | 1002 | =back |
2170 | 1003 | |
2171 | = | |
1004 | =head3 機能性を変更するために、スキーマを変更する | |
2172 | 1005 | |
2173 | ||
1006 | As your application evolves, it may be necessary to modify your schema to | |
1007 | change functionality. Once the changes are made to your schema in DBIx::Class, | |
1008 | export the modified schema as before, taking care not to overwrite the original: | |
2174 | 1009 | |
2175 | ||
1010 | アプリケーションが進化するにつれ、機能性を変更するために、スキーマを修正する必要があるでしょう。 | |
1011 | DBIx::Classでスキーマを変更したら、以前のように修正されたスキーマをエクスポートします。 | |
1012 | オリジナルのスキーマを上書きしないように気を付けましょう: | |
2176 | 1013 | |
2177 | B | |
1014 | sqlt --from SQL::Translator::DBIx::Class | |
1015 | --to MySQL | |
1016 | --DBIx::Class "Anything.pm" > Schema2.mysql.sql | |
2178 | 1017 | |
2179 | ||
1018 | Next, use sqlt-diff to create an SQL script that will update the customer's | |
1019 | database schema: | |
2180 | 1020 | |
2181 | ||
1021 | 次に、sqlt-diffを使って、顧客のデータベーススキーマを更新するSQLスクリプトを作ります: | |
2182 | to change functionality. Once the changes are made to your schema in | |
2183 | DBIx::Class, export the modified schema and the conversion scripts as | |
2184 | in L</Creating DDL SQL>. | |
2185 | 1022 | |
2186 | ||
1023 | sqlt-diff --to MySQL Schema1=MySQL Schema2=MySQL > SchemaUpdate.mysql.sql | |
2187 | 1024 | |
2188 | ||
1025 | =head3 顧客に更新をデプロイします | |
2189 | DBIx::Classでスキーマを変更したら、以前のように修正されたスキーマをエクスポートし、 | |
2190 | L</Creating DDL SQL>にあるような変換スクリプトを使います | |
2191 | 1026 | |
2192 | ||
1027 | The schema update can be deployed to customers using the same method as before. | |
2193 | 1028 | |
2194 | ||
1029 | スキーマの更新は以前と同じようにして、顧客にデプロイされます。 | |
2195 | 1030 | |
2196 | ||
1031 | =head2 SQL::Abstract::Limit のために、リミットの方言を設定する | |
2197 | Schema class. This will add a new table to your database called | |
2198 | C<dbix_class_schema_vesion> which will keep track of which version is installed | |
2199 | and warn if the user tries to run a newer schema version than the | |
2200 | database thinks it has. | |
2201 | 1032 | |
2202 | ||
1033 | In some cases, SQL::Abstract::Limit cannot determine the dialect of | |
2203 | ||
1034 | the remote SQL server by looking at the database handle. This is a | |
1035 | common problem when using the DBD::JDBC, since the DBD-driver only | |
1036 | know that in has a Java-driver available, not which JDBC driver the | |
1037 | Java component has loaded. This specifically sets the limit_dialect | |
1038 | to Microsoft SQL-server (See more names in SQL::Abstract::Limit | |
1039 | -documentation. | |
2204 | 1040 | |
2205 | ||
1041 | 時には、SQL::Abstract::Limit はデータベースハンドルで見ていることで、 | |
1042 | リモートのSQLサーバの方言を決めれられない場合があります。 | |
1043 | これは、DBD::JDBCを使っているときの、よく知られた問題です。 | |
1044 | DBD-driver は Java-driver が利用できることを知っているだけで、 | |
1045 | どのJDBCドライバをJavaコンポーネントがロードしているかを知らないからです。 | |
1046 | 具体的に、Microsoft SQL-server のlimitの方言をセットします | |
1047 | (SQL::Abstract::Limitのドキュメントには、より多くの名前があります)。 | |
2206 | 1048 | |
2207 | ||
1049 | __PACKAGE__->storage->sql_maker->limit_dialect('mssql'); | |
2208 | 1050 | |
1051 | The JDBC bridge is one way of getting access to a MSSQL server from a platform | |
1052 | that Microsoft doesn't deliver native client libraries for. (e.g. Linux) | |
1053 | ||
1054 | JDBCブリッジはMicrosoftがネイティブのクライアントライブラリを配布していない | |
1055 | プラットフォーム(例えば、Linux)からMSSQLサーバへアクセスする1つの方法です。 | |
1056 | ||
1057 | =head2 生成されたSQLをクォートする | |
1058 | ||
2209 | 1059 | If the database contains column names with spaces and/or reserved words, they |
2210 | 1060 | need to be quoted in the SQL queries. This is done using: |
2211 | 1061 | |
2212 | =end original | |
2213 | ||
2214 | 1062 | データベースにスペースおよび/または予約語のついたカラム名がある場合、 |
2215 | 1063 | SQLクエリ内で、クォートされる必要があります。次のようにします: |
2216 | 1064 | |
2217 | | |
1065 | __PACKAGE__->storage->sql_maker->quote_char([ qw/[ ]/] ); | |
2218 | | |
1066 | __PACKAGE__->storage->sql_maker->name_sep('.'); | |
2219 | 1067 | |
2220 | =begin original | |
2221 | ||
2222 | 1068 | The first sets the quote characters. Either a pair of matching |
2223 | 1069 | brackets, or a C<"> or C<'>: |
2224 | 1070 | |
2225 | =end original | |
2226 | ||
2227 | 1071 | 1行目は、クォート文字をセットしています。ブラケットのペアか、C<">, C<'>です。 |
2228 | 1072 | |
2229 | | |
1073 | __PACKAGE__->storage->sql_maker->quote_char('"'); | |
2230 | 1074 | |
2231 | =begin original | |
2232 | ||
2233 | 1075 | Check the documentation of your database for the correct quote |
2234 | 1076 | characters to use. C<name_sep> needs to be set to allow the SQL |
2235 | generator to put the quotes the correct place | |
1077 | generator to put the quotes the correct place. | |
2236 | C<.> if not supplied. | |
2237 | 1078 | |
2238 | =end original | |
2239 | ||
2240 | 1079 | 正しいクォート文字を使うために、データベースのドキュメントをチェックしてください。 |
2241 | 1080 | C<name_sep>は、SQLジェネレーターが正しい場所にクォートを置くために、 |
2242 | セットしなければいけません。 | |
1081 | セットしなければいけません。 | |
2243 | 1082 | |
2244 | ||
1083 | =head2 メソッドのオーバーロード | |
2245 | L<DBIx::Class::Schema/connect>: | |
2246 | 1084 | |
2247 | | |
1085 | L<DBIx::Class> uses the L<Class::C3> package, which provides for redispatch of | |
2248 | | |
1086 | method calls. You have to use calls to C<next::method> to overload methods. | |
2249 | | |
1087 | More information on using L<Class::C3> with L<DBIx::Class> can be found in | |
2250 | 'db_password', | |
2251 | { | |
2252 | quote_char => '"', | |
2253 | name_sep => '.' | |
2254 | } | |
2255 | ) | |
2256 | ||
2257 | In some cases, quoting will be required for all users of a schema. To enforce | |
2258 | this, you can also overload the C<connection> method for your schema class: | |
2259 | ||
2260 | sub connection { | |
2261 | my $self = shift; | |
2262 | my $rv = $self->next::method( @_ ); | |
2263 | $rv->storage->sql_maker->quote_char([ qw/[ ]/ ]); | |
2264 | $rv->storage->sql_maker->name_sep('.'); | |
2265 | return $rv; | |
2266 | } | |
2267 | ||
2268 | =head2 Working with PostgreSQL array types | |
2269 | ||
2270 | You can also assign values to PostgreSQL array columns by passing array | |
2271 | references in the C<\%columns> (C<\%vals>) hashref of the | |
2272 | L<DBIx::Class::ResultSet/create> and L<DBIx::Class::Row/update> family of | |
2273 | methods: | |
2274 | ||
2275 | $resultset->create({ | |
2276 | numbers => [1, 2, 3] | |
2277 | }); | |
2278 | ||
2279 | $row->update( | |
2280 | { | |
2281 | numbers => [1, 2, 3] | |
2282 | }, | |
2283 | { | |
2284 | day => '2008-11-24' | |
2285 | } | |
2286 | ); | |
2287 | ||
2288 | In conditions (e.g. C<\%cond> in the L<DBIx::Class::ResultSet/search> family of | |
2289 | methods) you cannot directly use array references (since this is interpreted as | |
2290 | a list of values to be C<OR>ed), but you can use the following syntax to force | |
2291 | passing them as bind values: | |
2292 | ||
2293 | $resultset->search( | |
2294 | { | |
2295 | numbers => \[ '= ?', [numbers => [1, 2, 3]] ] | |
2296 | } | |
2297 | ); | |
2298 | ||
2299 | See L<SQL::Abstract/array_datatypes> and L<SQL::Abstract/Literal SQL with | |
2300 | placeholders and bind values (subqueries)> for more explanation. Note that | |
2301 | L<DBIx::Class> sets L<SQL::Abstract/bindtype> to C<columns>, so you must pass | |
2302 | the bind values (the C<[1, 2, 3]> arrayref in the above example) wrapped in | |
2303 | arrayrefs together with the column name, like this: | |
2304 | C<< [column_name => value] >>. | |
2305 | ||
2306 | =head2 Formatting DateTime objects in queries | |
2307 | ||
2308 | To ensure C<WHERE> conditions containing L<DateTime> arguments are properly | |
2309 | formatted to be understood by your RDBMS, you must use the C<DateTime> | |
2310 | formatter returned by L<DBIx::Class::Storage::DBI/datetime_parser> to format | |
2311 | any L<DateTime> objects you pass to L<search|DBIx::Class::ResultSet/search> | |
2312 | conditions. Any L<Storage|DBIx::Class::Storage> object attached to your | |
2313 | L<Schema|DBIx::Class::Schema> provides a correct C<DateTime> formatter, so | |
2314 | all you have to do is: | |
2315 | ||
2316 | my $dtf = $schema->storage->datetime_parser; | |
2317 | my $rs = $schema->resultset('users')->search( | |
2318 | { | |
2319 | signup_date => { | |
2320 | -between => [ | |
2321 | $dtf->format_datetime($dt_start), | |
2322 | $dtf->format_datetime($dt_end), | |
2323 | ], | |
2324 | } | |
2325 | }, | |
2326 | ); | |
2327 | ||
2328 | Without doing this the query will contain the simple stringification of the | |
2329 | C<DateTime> object, which almost never matches the RDBMS expectations. | |
2330 | ||
2331 | This kludge is necessary only for conditions passed to | |
2332 | L<DBIx::Class::ResultSet/search>, whereas | |
2333 | L<create|DBIx::Class::ResultSet/create>, | |
2334 | L<find|DBIx::Class::ResultSet/find>, | |
2335 | L<DBIx::Class::Row/update> (but not L<DBIx::Class::ResultSet/update>) are all | |
2336 | L<DBIx::Class::InflateColumn>-aware and will do the right thing when supplied | |
2337 | an inflated C<DateTime> object. | |
2338 | ||
2339 | =head2 Using Unicode | |
2340 | ||
2341 | When using unicode character data there are two alternatives - | |
2342 | either your database supports unicode characters (including setting | |
2343 | the utf8 flag on the returned string), or you need to encode/decode | |
2344 | data appropriately each time a string field is inserted into or | |
2345 | retrieved from the database. It is better to avoid | |
2346 | encoding/decoding data and to use your database's own unicode | |
2347 | capabilities if at all possible. | |
2348 | ||
2349 | The L<DBIx::Class::UTF8Columns> component handles storing selected | |
2350 | unicode columns in a database that does not directly support | |
2351 | unicode. If used with a database that does correctly handle unicode | |
2352 | then strange and unexpected data corrupt B<will> occur. | |
2353 | ||
2354 | The Catalyst Wiki Unicode page at | |
2355 | L<http://wiki.catalystframework.org/wiki/tutorialsandhowtos/using_unicode> | |
2356 | has additional information on the use of Unicode with Catalyst and | |
2357 | DBIx::Class. | |
2358 | ||
2359 | The following databases do correctly handle unicode data:- | |
2360 | ||
2361 | =head3 MySQL | |
2362 | ||
2363 | MySQL supports unicode, and will correctly flag utf8 data from the | |
2364 | database if the C<mysql_enable_utf8> is set in the connect options. | |
2365 | ||
2366 | my $schema = My::Schema->connection('dbi:mysql:dbname=test', | |
2367 | $user, $pass, | |
2368 | { mysql_enable_utf8 => 1} ); | |
2369 | ||
2370 | ||
2371 | When set, a data retrieved from a textual column type (char, | |
2372 | varchar, etc) will have the UTF-8 flag turned on if necessary. This | |
2373 | enables character semantics on that string. You will also need to | |
2374 | ensure that your database / table / column is configured to use | |
2375 | UTF8. See Chapter 10 of the mysql manual for details. | |
2376 | ||
2377 | See L<DBD::mysql> for further details. | |
2378 | ||
2379 | =head3 Oracle | |
2380 | ||
2381 | Information about Oracle support for unicode can be found in | |
2382 | L<DBD::Oracle/Unicode>. | |
2383 | ||
2384 | =head3 PostgreSQL | |
2385 | ||
2386 | PostgreSQL supports unicode if the character set is correctly set | |
2387 | at database creation time. Additionally the C<pg_enable_utf8> | |
2388 | should be set to ensure unicode data is correctly marked. | |
2389 | ||
2390 | my $schema = My::Schema->connection('dbi:Pg:dbname=test', | |
2391 | $user, $pass, | |
2392 | { pg_enable_utf8 => 1} ); | |
2393 | ||
2394 | Further information can be found in L<DBD::Pg>. | |
2395 | ||
2396 | =head3 SQLite | |
2397 | ||
2398 | SQLite version 3 and above natively use unicode internally. To | |
2399 | correctly mark unicode strings taken from the database, the | |
2400 | C<sqlite_unicode> flag should be set at connect time (in versions | |
2401 | of L<DBD::SQLite> prior to 1.27 this attribute was named | |
2402 | C<unicode>). | |
2403 | ||
2404 | my $schema = My::Schema->connection('dbi:SQLite:/tmp/test.db', | |
2405 | '', '', | |
2406 | { sqlite_unicode => 1} ); | |
2407 | ||
2408 | =head1 BOOTSTRAPPING/MIGRATING | |
2409 | ||
2410 | =head2 クラスベースからスキーマベースセットアップへの簡単な移行 | |
2411 | ||
2412 | =begin original | |
2413 | ||
2414 | You want to start using the schema-based approach to L<DBIx::Class> | |
2415 | (see L<DBIx::Class::Manual::Intro/Setting it up manually>), but have an | |
2416 | established class-based setup with lots of existing classes that you don't | |
2417 | want to move by hand. Try this nifty script instead: | |
2418 | ||
2419 | =end original | |
2420 | ||
2421 | L<DBIx::Class>へのスキーマベースのアプローチを使いたい(L<SchemaIntro.pod>をみてください)、 | |
2422 | でも、既存の大量のクラスで、従来のクラスベースのセットアップがあり、 | |
2423 | 手でそれらを動かしたくはないとします。手で動かす変わりに、下記の気の利いたスクリプトを | |
2424 | 試してみて下さい: | |
2425 | ||
2426 | use MyDB; | |
2427 | use SQL::Translator; | |
2428 | ||
2429 | my $schema = MyDB->schema_instance; | |
2430 | ||
2431 | my $translator = SQL::Translator->new( | |
2432 | debug => $debug || 0, | |
2433 | trace => $trace || 0, | |
2434 | no_comments => $no_comments || 0, | |
2435 | show_warnings => $show_warnings || 0, | |
2436 | add_drop_table => $add_drop_table || 0, | |
2437 | validate => $validate || 0, | |
2438 | parser_args => { | |
2439 | 'DBIx::Schema' => $schema, | |
2440 | }, | |
2441 | producer_args => { | |
2442 | 'prefix' => 'My::Schema', | |
2443 | }, | |
2444 | ); | |
2445 | ||
2446 | $translator->parser('SQL::Translator::Parser::DBIx::Class'); | |
2447 | $translator->producer('SQL::Translator::Producer::DBIx::Class::File'); | |
2448 | ||
2449 | my $output = $translator->translate(@args) or die | |
2450 | "Error: " . $translator->error; | |
2451 | ||
2452 | print $output; | |
2453 | ||
2454 | =begin original | |
2455 | ||
2456 | You could use L<Module::Find> to search for all subclasses in the MyDB::* | |
2457 | namespace, which is currently left as an exercise for the reader. | |
2458 | ||
2459 | =end original | |
2460 | ||
2461 | L<Module::Find>を使って、MyDB::*名前空間にある全てのサブクラスを探すことが出来ますが、 | |
2462 | これは、今のところ、読者への課題としておきます。 | |
2463 | ||
2464 | =head1 メソッドのオーバーロード | |
2465 | ||
2466 | =begin original | |
2467 | ||
2468 | L<DBIx::Class> uses the L<Class::C3> package, which provides for redispatch of | |
2469 | method calls, useful for things like default values and triggers. You have to | |
2470 | use calls to C<next::method> to overload methods. More information on using | |
2471 | L<Class::C3> with L<DBIx::Class> can be found in | |
2472 | 1088 | L<DBIx::Class::Manual::Component>. |
2473 | 1089 | |
2474 | =end original | |
2475 | ||
2476 | 1090 | L<DBIx::Class>はL<Class::C3>パッケージを使っています。L<Class::C3>はメソッドコールを |
2477 | 1091 | 再分岐させるために使われています。メソッドをオーバーロードするために、 |
2478 | 1092 | C<next::method>の呼び出しを使わなければいけません。 |
2479 | 1093 | L<DBIx::Class>とL<Class::C3>の利用に関する詳しい情報は、 |
2480 | 1094 | L<DBIx::Class::Manual::Component>を見てください。 |
2481 | 1095 | |
2482 | =head2 列のデフォルトの値を用意する | |
2483 | ||
2484 | =begin original | |
2485 | ||
2486 | It's as simple as overriding the C<new> method. Note the use of | |
2487 | C<next::method>. | |
2488 | ||
2489 | =end original | |
2490 | ||
2491 | 単純に、C<new>メソッドをオーバーライドします。 | |
2492 | C<next::method>の使いかたに注意してください。 | |
2493 | ||
2494 | sub new { | |
2495 | my ( $class, $attrs ) = @_; | |
2496 | ||
2497 | $attrs->{foo} = 'bar' unless defined $attrs->{foo}; | |
2498 | ||
2499 | my $new = $class->next::method($attrs); | |
2500 | ||
2501 | return $new; | |
2502 | } | |
2503 | ||
2504 | =begin original | |
2505 | ||
2506 | For more information about C<next::method>, look in the L<Class::C3> | |
2507 | documentation. See also L<DBIx::Class::Manual::Component> for more | |
2508 | ways to write your own base classes to do this. | |
2509 | ||
2510 | =end original | |
2511 | ||
2512 | C<next::method>についてより詳しくは、L<Class::C3>のドキュメントを参照してください。 | |
2513 | これをするための、自分自身のベースクラスを書くための、より多くの方法については、 | |
2514 | L<DBIx::CLass::Manual::Component>を見てください。 | |
2515 | ||
2516 | =begin original | |
2517 | ||
2518 | People looking for ways to do "triggers" with DBIx::Class are probably | |
2519 | just looking for this. | |
2520 | ||
2521 | =end original | |
2522 | ||
2523 | DBIx::Classで"triggers"をする方法を探している人も、これを探しているでしょう。 | |
2524 | ||
2525 | 1096 | =head3 他が変更されたらいつでもあるフィールドを変更する |
2526 | 1097 | |
2527 | ||
1098 | For example, say that you have three columns, C<id>, C<number>, and | |
2528 | ||
2529 | For example, say that you have three columns, C<id>, C<number>, and | |
2530 | 1099 | C<squared>. You would like to make changes to C<number> and have |
2531 | 1100 | C<squared> be automagically set to the value of C<number> squared. |
2532 | You can accomplish this by | |
1101 | You can accomplish this by overriding C<store_column>: | |
2533 | L<Class::Method::Modifiers>: | |
2534 | 1102 | |
2535 | =end original | |
2536 | ||
2537 | 1103 | 例えば、3つのカラムがあったとします。C<id>、C<number>、C<squared>。 |
2538 | 1104 | C<number>に変更を加え、C<squared>は自動的に、C<number>の二乗の値を |
2539 | セットしたいとします。C< | |
1105 | セットしたいとします。C<store_column>をオーバーロードすることで、 | |
2540 | ||
1106 | これができます: | |
2541 | 1107 | |
2542 | | |
1108 | sub store_column { | |
2543 | my ( | |
1109 | my ( $self, $name, $value ) = @_; | |
1110 | if ($name eq 'number') { | |
2545 | | |
1111 | $self->squared($value * $value); | |
2546 | my $value = $_[0]; | |
2547 | $self->squared( $value * $value ); | |
2548 | 1112 | } |
1113 | $self->next::method($name, $value); | |
2550 | $self->next::method(@_); | |
2551 | 1114 | } |
2552 | 1115 | |
2553 | =begin original | |
2554 | ||
2555 | 1116 | Note that the hard work is done by the call to C<next::method>, which |
2556 | 1117 | redispatches your call to store_column in the superclass(es). |
2557 | 1118 | |
2558 | =end original | |
2559 | ||
2560 | 1119 | C<next::method>を呼び出すことで、大変な仕事がされていることに注意しましょう。 |
2561 | 1120 | 呼び出しが、(複数の)スーパークラスのstore_columnに再分岐されてます: |
2562 | 1121 | |
2563 | ||
1122 | =head3 関連するオブジェクトを自動的に作る | |
2564 | and avoid storing the calculated value, it is safer to calculate when | |
2565 | needed, than rely on the data being in sync. | |
2566 | 1123 | |
2567 | ||
1124 | You might have a class C<Artist> which has many C<CD>s. Further, if you | |
2568 | ||
2569 | =begin original | |
2570 | ||
2571 | You might have a class C<Artist> which has many C<CD>s. Further, you | |
2572 | 1125 | want to create a C<CD> object every time you insert an C<Artist> object. |
2573 | 1126 | You can accomplish this by overriding C<insert> on your objects: |
2574 | 1127 | |
2575 | =end original | |
2576 | ||
2577 | 1128 | 多くのC<CD>を持ったC<Artist>クラスがあるとします。 |
2578 | 1129 | さらに、C<Artist>オブジェクトをインサートする度毎にC<CD>オブジェクトを |
2579 | 1130 | 作りたいとします。これは、オブジェクトのC<insert>をオーバロードすればできます: |
2580 | 1131 | |
2581 | 1132 | sub insert { |
2582 | 1133 | my ( $self, @args ) = @_; |
2583 | 1134 | $self->next::method(@args); |
2584 | $self->c | |
1135 | $self->cds->new({})->fill_from_artist($self)->insert; | |
2585 | 1136 | return $self; |
2586 | 1137 | } |
2587 | 1138 | |
2588 | ||
1139 | where C<fill_from_artist> is a method you specify in C<CD> which sets | |
2589 | a | |
1140 | values in C<CD> based on the data in the C<Artist> object you pass in. | |
2590 | L<DBIx::Class::Storage::TxnScopeGuard>: | |
2591 | 1141 | |
2592 | ||
1142 | C<fill_from_artist>はC<CD>で指定しているメソッドで、 | |
2593 | ||
1143 | 渡したC<Artist>オブジェクトのデータに基づいた値をCDにセットします。 | |
2594 | 1144 | |
2595 | ||
1145 | =head2 Data::Dumperを使って、DBIx::Classをデバッグする | |
2596 | 1146 | |
2597 | $self->next::method(@args); | |
2598 | $self->create_related ('cds', \%initial_cd_data ); | |
2599 | ||
2600 | $guard->commit; | |
2601 | ||
2602 | return $self | |
2603 | } | |
2604 | ||
2605 | =head2 カラムのアクセサをラッピング/オーバーロードする | |
2606 | ||
2607 | B<Problem:> | |
2608 | ||
2609 | B<問題:> | |
2610 | ||
2611 | =begin original | |
2612 | ||
2613 | Say you have a table "Camera" and want to associate a description | |
2614 | with each camera. For most cameras, you'll be able to generate the description from | |
2615 | the other columns. However, in a few special cases you may want to associate a | |
2616 | custom description with a camera. | |
2617 | ||
2618 | =end original | |
2619 | ||
2620 | "Camera"テーブルがあったとして、それぞれのカメラについて、 | |
2621 | 説明を関連付けたいとします。ほとんどのカメラでは、他のカラムから説明を生成できるでしょう。 | |
2622 | しかし、特別な数ケースでは、カメラのカスタムの説明を関連付けたいとします。 | |
2623 | ||
2624 | B<Solution:> | |
2625 | ||
2626 | B<解:> | |
2627 | ||
2628 | =begin original | |
2629 | ||
2630 | In your database schema, define a description field in the "Camera" table that | |
2631 | can contain text and null values. | |
2632 | ||
2633 | =end original | |
2634 | ||
2635 | データベーススキーマで、"Camera"にdescriptionフィールドが定義し、 | |
2636 | textとnullの値を含むことをできるようにします。 | |
2637 | ||
2638 | =begin original | |
2639 | ||
2640 | In DBIC, we'll overload the column accessor to provide a sane default if no | |
2641 | custom description is defined. The accessor will either return or generate the | |
2642 | description, depending on whether the field is null or not. | |
2643 | ||
2644 | =end original | |
2645 | ||
2646 | DBICは、カスタムの description が定義されていなければ、 | |
2647 | 提供されているまともなデフォルトのカラムアクセサをオーバーロードできます。 | |
2648 | フィールドがnullかnullでないかに依存して、アクセサはdescriptionを返すか生成します。 | |
2649 | ||
2650 | =begin original | |
2651 | ||
2652 | First, in your "Camera" schema class, define the description field as follows: | |
2653 | ||
2654 | =end original | |
2655 | ||
2656 | まず、"Camera"スキーマクラスで、下記のようにdescriptionフィールドを定義します: | |
2657 | ||
2658 | __PACKAGE__->add_columns(description => { accessor => '_description' }); | |
2659 | ||
2660 | =begin original | |
2661 | ||
2662 | Next, we'll define the accessor-wrapper subroutine: | |
2663 | ||
2664 | =end original | |
2665 | ||
2666 | 次に、アクセサラッパーサブルーチンを定義します: | |
2667 | ||
2668 | sub description { | |
2669 | my $self = shift; | |
2670 | ||
2671 | # If there is an update to the column, we'll let the original accessor | |
2672 | # deal with it. | |
2673 | return $self->_description(@_) if @_; | |
2674 | ||
2675 | # Fetch the column value. | |
2676 | my $description = $self->_description; | |
2677 | ||
2678 | # If there's something in the description field, then just return that. | |
2679 | return $description if defined $description && length $descripton; | |
2680 | ||
2681 | # Otherwise, generate a description. | |
2682 | return $self->generate_description; | |
2683 | } | |
2684 | ||
2685 | =head1 デバッギングとプロファイリング | |
2686 | ||
2687 | =head2 Data::Dumperと、DBIx::Classオブジェクト | |
2688 | ||
2689 | =begin original | |
2690 | ||
2691 | 1147 | L<Data::Dumper> can be a very useful tool for debugging, but sometimes it can |
2692 | 1148 | be hard to find the pertinent data in all the data it can generate. |
2693 | 1149 | Specifically, if one naively tries to use it like so, |
2694 | 1150 | |
2695 | =end original | |
2696 | ||
2697 | 1151 | L<Data::Dumper> はデバッグにとても便利なツールです。ですが、 |
2698 | 1152 | 生成された全てのデータの中の、該当のデータを見付けるのが難しい時があります。 |
2699 | ||
1153 | 次のように単純に使おうとしたら、 | |
2700 | 1154 | |
2701 | 1155 | use Data::Dumper; |
2702 | 1156 | |
2703 | 1157 | my $cd = $schema->resultset('CD')->find(1); |
2704 | 1158 | print Dumper($cd); |
2705 | 1159 | |
2706 | =begin original | |
2707 | ||
2708 | 1160 | several pages worth of data from the CD object's schema and result source will |
2709 | 1161 | be dumped to the screen. Since usually one is only interested in a few column |
2710 | 1162 | values of the object, this is not very helpful. |
2711 | 1163 | |
2712 | =end original | |
2713 | ||
2714 | 1164 | 複数ページにわたり、CDオブジェクトのスキーマと結果のソースが、複数 |
2715 | 1165 | ページにわたるデータとなってスクリーンにダンプされます。ですが、 |
2716 | 1166 | 普通はオブジェクトの数カラムの値の1つのみに興味があるので、これでは、 |
2717 | 1167 | あまり便利ではありません。 |
2718 | 1168 | |
2719 | =begin original | |
2720 | ||
2721 | 1169 | Luckily, it is possible to modify the data before L<Data::Dumper> outputs |
2722 | 1170 | it. Simply define a hook that L<Data::Dumper> will call on the object before |
2723 | 1171 | dumping it. For example, |
2724 | 1172 | |
2725 | =end original | |
2726 | ||
2727 | 1173 | 幸運にも、L<Data::Dumper>が出力する前にデータを加工することが出来ます。 |
2728 | 1174 | 簡単にフックを定義すると、L<Data::Dumper>がダンプする前に、オブジェクトで |
2729 | 1175 | それを呼び出します。 |
2730 | 1176 | |
2731 | 1177 | package My::DB::CD; |
2732 | 1178 | |
2733 | 1179 | sub _dumper_hook { |
2734 | 1180 | $_[0] = bless { |
2735 | 1181 | %{ $_[0] }, |
2736 | 1182 | result_source => undef, |
2737 | 1183 | }, ref($_[0]); |
2738 | 1184 | } |
2739 | 1185 | |
2740 | 1186 | [...] |
2741 | 1187 | |
2742 | 1188 | use Data::Dumper; |
2743 | 1189 | |
2744 | 1190 | local $Data::Dumper::Freezer = '_dumper_hook'; |
2745 | 1191 | |
2746 | 1192 | my $cd = $schema->resultset('CD')->find(1); |
2747 | 1193 | print Dumper($cd); |
2748 | 1194 | # dumps $cd without its ResultSource |
2749 | 1195 | |
2750 | =begin original | |
2751 | ||
2752 | 1196 | If the structure of your schema is such that there is a common base class for |
2753 | 1197 | all your table classes, simply put a method similar to C<_dumper_hook> in the |
2754 | 1198 | base class and set C<$Data::Dumper::Freezer> to its name and L<Data::Dumper> |
2755 | 1199 | will automagically clean up your data before printing it. See |
2756 | 1200 | L<Data::Dumper/EXAMPLES> for more information. |
2757 | 1201 | |
2758 | =end original | |
2759 | ||
2760 | 1202 | スキーマの構造が、全てのテーブルクラスのための共通のベースクラスがあるような |
2761 | 1203 | ものであれば、単純に、ベースクラスに、C<_dumper_hook>と同じようなメソッドを作り、 |
2762 | 1204 | C<$Data::Dumper::Freezer>にその名前をセットします。 |
2763 | 1205 | L<Data::Dumper>は、自動的に、データを出力する前に、きれいにします。 |
2764 | 1206 | L<Data::Dumper/EXAMPLES>により詳しい情報ががあります。 |
2765 | 1207 | |
2766 | =head2 | |
1208 | =head2 列オブジェクトのスキーマを得る | |
2767 | 1209 | |
2768 | ||
1210 | It is possible to get a Schema object from a row object like so: | |
2769 | 1211 | |
2770 | ||
1212 | 次のようにして、列のオブジェクトからスキーマを得ることができます: | |
1213 | ||
1214 | my $schema = $cd->result_source->schema; | |
1215 | # use the schema as normal: | |
1216 | my $artist_rs = $schema->resultset('Artist'); | |
1217 | ||
1218 | This can be useful when you don't want to pass around a Schema object to every | |
1219 | method. | |
1220 | ||
1221 | 全てのメソッドで、スキーマオブジェクトを順に回したくなければ、便利でしょう。 | |
1222 | ||
1223 | =head2 プロファイリング | |
1224 | ||
1225 | When you enable L<DBIx::Class::Storage::DBI>'s debugging it prints the SQL | |
2771 | 1226 | executed as well as notifications of query completion and transaction |
2772 | 1227 | begin/commit. If you'd like to profile the SQL you can subclass the |
2773 | 1228 | L<DBIx::Class::Storage::Statistics> class and write your own profiling |
2774 | 1229 | mechanism: |
2775 | 1230 | |
2776 | ||
1231 | L<DBIx::Class::Storage::DBI>のデバッギングを有効にすれば、 | |
2777 | ||
2778 | L<DBIx::Class::Storage>のデバッギングを有効にすれば、 | |
2779 | 1232 | 実行されたSQLだけでなく、クエリの完了や、トランザクションの開始/コミット |
2780 | 1233 | も、出力します。SQLを分析したければ、 L<DBIx::Class::Storage::Statistics> |
2781 | 1234 | クラスのサブクラスを作り、自分自身のプロファイリングメカニズムを書けます: |
2782 | 1235 | |
2783 | 1236 | package My::Profiler; |
2784 | 1237 | use strict; |
2785 | 1238 | |
2786 | 1239 | use base 'DBIx::Class::Storage::Statistics'; |
2787 | 1240 | |
2788 | 1241 | use Time::HiRes qw(time); |
2789 | 1242 | |
2790 | 1243 | my $start; |
2791 | 1244 | |
2792 | 1245 | sub query_start { |
2793 | 1246 | my $self = shift(); |
2794 | 1247 | my $sql = shift(); |
2795 | my | |
1248 | my $params = @_; | |
2796 | 1249 | |
2797 | | |
1250 | print "Executing $sql: ".join(', ', @params)."\n"; | |
2798 | 1251 | $start = time(); |
2799 | 1252 | } |
2800 | 1253 | |
2801 | 1254 | sub query_end { |
2802 | 1255 | my $self = shift(); |
2803 | 1256 | my $sql = shift(); |
2804 | 1257 | my @params = @_; |
2805 | 1258 | |
2806 | | |
1259 | printf("Execution took %0.4f seconds.\n", time() - $start); | |
2807 | $self->print("Execution took $elapsed seconds.\n"); | |
2808 | 1260 | $start = undef; |
2809 | 1261 | } |
2810 | 1262 | |
2811 | 1263 | 1; |
2812 | 1264 | |
2813 | 1265 | You can then install that class as the debugging object: |
2814 | 1266 | |
2815 | それから、このクラスを、デバッギングオブジェクトにインストール | |
1267 | それから、このクラスを、デバッギングオブジェクトにインストールします: | |
2816 | 1268 | |
2817 | __PACKAGE__->storage->debugobj(new My::Profiler()); | |
1269 | __PACKAGE__->storage()->debugobj(new My::Profiler()); | |
2818 | __PACKAGE__->storage->debug(1); | |
1270 | __PACKAGE__->storage()->debug(1); | |
2819 | 1271 | |
2820 | 1272 | A more complicated example might involve storing each execution of SQL in an |
2821 | 1273 | array: |
2822 | 1274 | |
2823 | 1275 | より複雑な例としては、配列に実行する各SQLを貯めておくようなものを含むでしょう: |
2824 | 1276 | |
2825 | 1277 | sub query_end { |
2826 | 1278 | my $self = shift(); |
2827 | 1279 | my $sql = shift(); |
2828 | 1280 | my @params = @_; |
2829 | 1281 | |
2830 | 1282 | my $elapsed = time() - $start; |
2831 | 1283 | push(@{ $calls{$sql} }, { |
2832 | 1284 | params => \@params, |
2833 | 1285 | elapsed => $elapsed |
2834 | 1286 | }); |
2835 | 1287 | } |
2836 | 1288 | |
2837 | =begin original | |
2838 | ||
2839 | 1289 | You could then create average, high and low execution times for an SQL |
2840 | 1290 | statement and dig down to see if certain parameters cause aberrant behavior. |
2841 | You might want to check out L<DBIx::Class::QueryLog> as well. | |
2842 | 1291 | |
2843 | =end original | |
2844 | ||
2845 | 1292 | それから、SQLステートメントの平均、最長、最短実行時間を取れますし、ある |
2846 | 1293 | パラメータが異常な振る舞いを引き起こしていれば、掘り下げることも出来るでしょう。 |
2847 | L<DBIx::Class::QueryLog>もチェックしたいいかもしれません。 | |
2848 | 1294 | |
2849 | =head | |
1295 | =head2 最後にデータベースにインサートしたプライマリキーの値を取りたい | |
2850 | 1296 | |
2851 | ||
1297 | last_insert_id を取るともいいます。 | |
2852 | 1298 | |
2853 | ||
1299 | If you are using PK::Auto, this is straightforward: | |
2854 | 1300 | |
2855 | ||
1301 | PK::Autoを使っているのなら、直接: | |
2856 | 1302 | |
2857 | = | |
1303 | my $foo = $rs->create(\%blah); | |
1304 | # do more stuff | |
1305 | my $id = $foo->id; # foo->my_primary_key_field will also work. | |
2858 | 1306 | |
2859 | ||
1307 | If you are not using autoincrementing primary keys, this will probably | |
1308 | not work, but then you already know the value of the last primary key anyway. | |
2860 | 1309 | |
2861 | ||
1310 | オートインクリメントのプライマリキーを使っていないのなら、おそらく動きません。 | |
1311 | ですが、すでに、プライマリキーの値を知っていることでしょう。 | |
2862 | 1312 | |
2863 | ||
1313 | =head2 DBIx::Classのプロキシクラスを動的にサブクラス化する | |
2864 | ||
1314 | (AKA multi-class object inflation from one table) | |
2865 | 1315 | |
2866 | ||
1316 | (AKA 1つのテーブルからマルチクラスのオブジェクトに展開する) | |
1317 | ||
1318 | L<DBIx::Class> classes are proxy classes, therefore some different | |
1319 | techniques need to be employed for more than basic subclassing. In | |
1320 | this example we have a single user table that carries a boolean bit | |
1321 | for admin. We would like like to give the admin users | |
1322 | objects(L<DBIx::Class::Row>) the same methods as a regular user but | |
1323 | also special admin only methods. It doesn't make sense to create two | |
1324 | seperate proxy-class files for this. We would be copying all the user | |
1325 | methods into the Admin class. There is a cleaner way to accomplish | |
1326 | this. | |
2867 | 1327 | |
2868 | ||
1328 | L<DBIx::Class>クラスはプロキシクラスです。そのため、基本的なサブクラス化以上に、 | |
2869 | ||
1329 | いくつかの違ったテクニックが必要とされます。 | |
2870 | ||
1330 | この例では、管理者用に真偽値を持っているユーザーテーブルがあります。 | |
1331 | 管理者ユーザーには、オブジェクト(L<DBIx::Class::Row>)のメソッドを、 | |
1332 | 普通のユーザーと同じようにあたえますが、管理者のみの特別なメソッドも、 | |
1333 | あたえたいとします。このために2つのプロキシクラスファイルに分割するのは | |
1334 | 理にかないません。Adminクラスに全てのユーザークラスのメソッドをコピー | |
1335 | することになります。これをするために、よりすっきりした方法があります。 | |
2871 | 1336 | |
2872 | ||
1337 | Overriding the C<inflate_result> method within the User proxy-class | |
2873 | ||
1338 | gives us the effect we want. This method is called by | |
1339 | L<DBIx::Class::ResultSet> when inflating a result from storage. So we | |
1340 | grab the object being returned, inspect the values we are looking for, | |
1341 | bless it if it's an admin object, and then return it. See the example | |
1342 | below: | |
2874 | 1343 | |
2875 | ||
1344 | ユーザーのプロキシクラス内でC<inflate_result>メソッドをオーバーライドすることで、 | |
2876 | ||
1345 | 望んでいる効果が得られます。このメソッドは、ストレージから結果が展開されるときに、 | |
2877 | l | |
1346 | L<DBIx::Class::ResultSet>によって呼ばれます。 | |
1347 | 返されたオブジェクトを掴んだら、探している値を調べ、管理者オブジェクトであれば、 | |
1348 | それをblessします。下の例を見てください: | |
2878 | 1349 | |
2879 | ||
1350 | B<Schema Definition> | |
2880 | 1351 | |
2881 | ||
1352 | package DB::Schema; | |
2882 | ||
1353 | ||
1354 | use base qw/DBIx::Class::Schema/; | |
1355 | ||
1356 | __PACKAGE__->load_classes(qw/User/); | |
1357 | ||
1358 | ||
1359 | B<Proxy-Class definitions> | |
2883 | 1360 | |
2884 | ||
1361 | package DB::Schema::User; | |
1362 | ||
1363 | use strict; | |
1364 | use warnings; | |
1365 | use base qw/DBIx::Class/; | |
1366 | ||
1367 | ### Defined what our admin class is for ensure_class_loaded | |
1368 | my $admin_class = __PACKAGE__ . '::Admin'; | |
1369 | ||
1370 | __PACKAGE__->load_components(qw/Core/); | |
1371 | ||
1372 | __PACKAGE__->table('users'); | |
1373 | ||
1374 | __PACKAGE__->add_columns(qw/user_id email password | |
1375 | firstname lastname active | |
1376 | admin/); | |
1377 | ||
1378 | __PACKAGE__->set_primary_key('user_id'); | |
1379 | ||
1380 | sub inflate_result { | |
1381 | my $self = shift; | |
1382 | my $ret = $self->next::method(@_); | |
1383 | if( $ret->admin ) {### If this is an admin rebless for extra functions | |
1384 | $self->ensure_class_loaded( $admin_class ); | |
1385 | bless $ret, $admin_class; | |
1386 | } | |
1387 | return $ret; | |
1388 | } | |
1389 | ||
1390 | sub hello { | |
1391 | print "I am a regular user.\n"; | |
1392 | return ; | |
1393 | } | |
1394 | ||
1395 | ||
1396 | package DB::Schema::User::Admin; | |
1397 | ||
1398 | use strict; | |
1399 | use warnings; | |
1400 | use base qw/DB::Schema::User/; | |
1401 | ||
1402 | sub hello | |
1403 | { | |
1404 | print "I am an admin.\n"; | |
1405 | return; | |
1406 | } | |
1407 | ||
1408 | sub do_admin_stuff | |
1409 | { | |
1410 | print "I am doing admin stuff\n"; | |
1411 | return ; | |
1412 | } | |
1413 | ||
1414 | B<Test File> test.pl | |
2885 | 1415 | |
2886 | ||
1416 | use warnings; | |
1417 | use strict; | |
1418 | use DB::Schema; | |
1419 | ||
1420 | my $user_data = { email => 'someguy@place.com', | |
1421 | password => 'pass1', | |
1422 | admin => 0 }; | |
1423 | ||
1424 | my $admin_data = { email => 'someadmin@adminplace.com', | |
1425 | password => 'pass2', | |
1426 | admin => 1 }; | |
1427 | ||
1428 | my $schema = DB::Schema->connection('dbi:Pg:dbname=test'); | |
1429 | ||
1430 | $schema->resultset('User')->create( $user_data ); | |
1431 | $schema->resultset('User')->create( $admin_data ); | |
1432 | ||
1433 | ### Now we search for them | |
1434 | my $user = $schema->resultset('User')->single( $user_data ); | |
1435 | my $admin = $schema->resultset('User')->single( $admin_data ); | |
1436 | ||
1437 | print ref $user, "\n"; | |
1438 | print ref $admin, "\n"; | |
1439 | ||
1440 | print $user->password , "\n"; # pass1 | |
1441 | print $admin->password , "\n";# pass2; inherited from User | |
1442 | print $user->hello , "\n";# I am a regular user. | |
1443 | print $admin->hello, "\n";# I am an admin. | |
1444 | ||
1445 | ### The statement below will NOT print | |
1446 | print "I can do admin stuff\n" if $user->can('do_admin_stuff'); | |
1447 | ### The statement below will print | |
1448 | print "I can do admin stuff\n" if $admin->can('do_admin_stuff'); | |
2887 | 1449 | |
2888 | = | |
1450 | =head2 高速に結果を得るために、オブジェクトの作成をスキップしたい | |
2889 | 1451 | |
2890 | ||
1452 | DBIx::Class is not built for speed, it's built for convenience and | |
1453 | ease of use, but sometimes you just need to get the data, and skip the | |
1454 | fancy objects. Luckily this is also fairly easy using | |
1455 | C<inflate_result>: | |
2891 | 1456 | |
2892 | ||
1457 | DBIx::Class はスピードのためには作られておらず、DBIx::Classは、 | |
2893 | ||
1458 | 利便性と使い易さのために作られました。ですが、時には、データをただ | |
2894 | ||
1459 | 取得しなければいけないだけの時があり、素敵なオブジェクトはスキップ | |
1460 | したい場合もあるでしょう。幸運なことに、この用途には、C<inflate_result> | |
1461 | が、実に簡単に使えます。 | |
2895 | 1462 | |
2896 | ||
1463 | # Define a class which just returns the results as a hashref: | |
2897 | ||
1464 | package My::HashRefInflator; | |
2898 | application. | |
2899 | 1465 | |
2900 | ||
1466 | ## $me is the hashref of cols/data from the immediate resultsource | |
1467 | ## $prefetch is a deep hashref of all the data from the prefetched | |
1468 | ## related sources. | |
2901 | 1469 | |
2902 | ||
1470 | sub mk_hash { | |
2903 | ||
1471 | my ($me, $rest) = @_; | |
2904 | classes dynamically based on the database schema then there will be a | |
2905 | significant startup delay. | |
2906 | 1472 | |
2907 | ||
1473 | return { %$me, | |
2908 | ||
1474 | map { ($_ => mk_hash(@{$rest->{$_}})) } keys %$rest | |
2909 | ||
1475 | }; | |
2910 | ||
1476 | } | |
2911 | L<dump_directory|DBIx::Class::Schema::Loader/dump_directory> for more | |
2912 | details on creating static schemas from a database). | |
2913 | 1477 | |
2914 | ||
1478 | sub inflate_result { | |
1479 | my ($self, $source, $me, $prefetch) = @_; | |
1480 | return mk_hash($me, $prefetch); | |
1481 | } | |
2915 | 1482 | |
2916 | ||
1483 | # Change the object inflation to a hashref for just this resultset: | |
1484 | $rs->result_class('My::HashRefInflator'); | |
2917 | 1485 | |
2918 | | |
1486 | my $datahashref = $rs->next; | |
2919 | | |
1487 | foreach my $col (keys %$datahashref) { | |
1488 | if(!ref($datahashref->{$col})) { | |
1489 | # It's a plain value | |
1490 | } | |
1491 | elsif(ref($datahashref->{$col} eq 'HASH')) { | |
1492 | # It's a related value in a hashref | |
1493 | } | |
1494 | } | |
2920 | 1495 | |
2921 | ||
1496 | =head2 find_or_create が見付けたのか、列を作ったのかを知りたい? | |
2922 | 1497 | |
2923 | | |
1498 | Just use C<find_or_new> instead, then check C<in_storage>: | |
2924 | 1499 | |
2925 | ||
1500 | C<find_or_new>を代わりに使ってください。それから、C<in_storage>をチェックします: | |
2926 | __PACKAGE__->load_components(qw/InflateColumn::DateTime/); | |
2927 | 1; | |
2928 | 1501 | |
2929 | ||
1502 | my $obj = $rs->find_or_new({ blah => 'blarg' }); | |
1503 | unless ($obj->in_storage) { | |
1504 | $obj->insert; | |
1505 | # do whatever else you wanted if it was a new row | |
1506 | } | |
2930 | 1507 | |
2931 | ||
1508 | =head3 カラムのアクセサをラッピング/オーバーロードする | |
2932 | 1509 | |
2933 | ||
1510 | Problem: Say you have a table "Camera" and want to associate a description | |
2934 | ||
1511 | with each camera. For most cameras, you'll be able to generate the description from | |
1512 | the other columns. However, in a few special cases you may want to associate a | |
1513 | custom description with a camera. | |
2935 | 1514 | |
2936 | ||
1515 | 問題: "Camera"テーブルがあったとして、それぞれのカメラについて、 | |
1516 | 説明を関連付けたいとします。ほとんどのカメラでは、他のカラムから説明を生成できるでしょう。 | |
1517 | しかし、特別な数ケースでは、カメラのカスタムの説明を関連付けたいとします。 | |
2937 | 1518 | |
2938 | ||
1519 | Solution: | |
2939 | 1520 | |
2940 | ||
1521 | 解: | |
2941 | 1522 | |
2942 | ||
1523 | In your database schema, define a description field in the "Camera" table that | |
2943 | ||
1524 | can contain text and null values. | |
2944 | classes you wish to load will remove the overhead of | |
2945 | L<Module::Find|Module::Find> and the related directory operations: | |
2946 | 1525 | |
2947 | ||
1526 | データベーススキーマで、"Camera"にdescriptionフィールドが定義し、 | |
1527 | textとnullの値を含むことをできるようにします。 | |
2948 | 1528 | |
2949 | I | |
1529 | In DBIC, we'll overload the column accessor to provide a sane default if no | |
2950 | s | |
1530 | custom description is defined. The accessor will either return or generate the | |
2951 | ||
1531 | description, depending on whether the field is null or not. | |
2952 | 1532 | |
2953 | ||
1533 | DBICは、カスタムの description が定義されていなければ、 | |
1534 | 提供されているまともなデフォルトのカラムアクセサをオーバーロードできます。 | |
1535 | フィールドがnullかnullでないかに依存して、アクセサはdescriptionを返すか生成します。 | |
2954 | 1536 | |
2955 | ||
1537 | First, in your "Camera" schema class, define the description field as follows: | |
2956 | 1538 | |
2957 | ||
1539 | まず、"Camera"スキーマクラスで、下記のようにdescriptionフィールドを定義します: | |
2958 | This is normally a good idea, but if too many statements are cached, the database may use too much | |
2959 | memory and may eventually run out and fail entirely. If you suspect this may be the case, you may want | |
2960 | to examine DBI's L<< CachedKids|DBI/CachedKidsCachedKids_(hash_ref) >> hash: | |
2961 | 1540 | |
2962 | | |
1541 | __PACKAGE__->add_columns(description => { accessor => '_description' }); | |
2963 | print for keys %{$schema->storage->dbh->{CachedKids}}; | |
2964 | # get a count of currently cached prepared statements | |
2965 | my $count = scalar keys %{$schema->storage->dbh->{CachedKids}}; | |
2966 | 1542 | |
2967 | ||
1543 | Next, we'll define the accessor-wrapper subroutine: | |
2968 | database: | |
2969 | 1544 | |
2970 | ||
1545 | 次に、アクセサラッパーサブルーチンを定義します: | |
2971 | delete @{$kids}{keys %$kids} if scalar keys %$kids > 100; | |
2972 | 1546 | |
2973 | ||
1547 | sub description { | |
2974 | ||
1548 | my $self = shift; | |
2975 | 1549 | |
2976 | | |
1550 | # If there is an update to the column, we'll let the original accessor | |
2977 | | |
1551 | # deal with it. | |
2978 | | |
1552 | return $self->_description(@_) if @_; | |
2979 | ||
2980 | | |
1554 | # Fetch the column value. | |
1555 | my $description = $self->_description; | |
1556 | ||
1557 | # If there's something in the description field, then just return that. | |
1558 | return $description if defined $description && length $descripton; | |
1559 | ||
1560 | # Otherwise, generate a description. | |
1561 | return $self->generate_description; | |
1562 | } | |
2981 | 1563 | |
2982 | 1564 | =head1 翻訳について |
2983 | 1565 | |
2984 | 1566 | 翻訳者:加藤敦 (ktat.is at gmail.com) |
2985 | 1567 | |
2986 | 1568 | Perlドキュメント日本語訳 Project にて、 |
2987 | 1569 | Perlモジュール、ドキュメントの翻訳を行っております。 |
2988 | 1570 | |
2989 | 1571 | http://perldocjp.sourceforge.jp/ |
2990 | 1572 | http://sourceforge.jp/projects/perldocjp/ |
2991 | 1573 | http://www.freeml.com/perldocjp/ |
2992 | 1574 | http://www.perldoc.jp |
2993 | 1575 | |
2994 | 1576 | =cut |