might_have test for castaway to break
[dbsrgits/DBIx-Class.git] / t / 96multi_create.t
CommitLineData
33dd4e80 1use strict;
af2d42c0 2use warnings;
33dd4e80 3
04ec3909 4use Test::More;
33dd4e80 5use lib qw(t/lib);
6use DBICTest;
7
51f30f72 8plan tests => 70;
04ec3909 9
33dd4e80 10my $schema = DBICTest->init_schema();
11
c45f4e10 12# simple create + parent (the stuff $rs belongs_to)
04ec3909 13eval {
c45f4e10 14 my $cd = $schema->resultset('CD')->create({
04ec3909 15 artist => {
16 name => 'Fred Bloggs'
17 },
18 title => 'Some CD',
19 year => 1996
20 });
21
c45f4e10 22 isa_ok($cd, 'DBICTest::CD', 'Created CD object');
23 isa_ok($cd->artist, 'DBICTest::Artist', 'Created related Artist');
24 is($cd->artist->name, 'Fred Bloggs', 'Artist created correctly');
25};
26diag $@ if $@;
27
28# same as above but the child and parent have no values,
29# except for an explicit parent pk
30eval {
31 my $bm_rs = $schema->resultset('Bookmark');
32 my $bookmark = $bm_rs->create({
33 link => {
34 id => 66,
35 },
36 });
37
38 isa_ok($bookmark, 'DBICTest::Bookmark', 'Created Bookrmark object');
39 isa_ok($bookmark->link, 'DBICTest::Link', 'Created related Link');
40 is (
41 $bm_rs->search (
42 { 'link.title' => $bookmark->link->title },
43 { join => 'link' },
44 )->count,
45 1,
46 'Bookmark and link made it to the DB',
47 );
04ec3909 48};
49diag $@ if $@;
50
51# create over > 1 levels of has_many create (A => { has_many => { B => has_many => C } } )
52eval {
53 my $artist = $schema->resultset('Artist')->create(
54 { name => 'Fred 2',
55 cds => [
56 { title => 'Music to code by',
57 year => 2007,
58 tags => [
59 { 'tag' => 'rock' },
60 ],
61 },
51f30f72 62 ],
63 }
64 );
04ec3909 65
66 isa_ok($artist, 'DBICTest::Artist', 'Created Artist');
67 is($artist->name, 'Fred 2', 'Artist created correctly');
68 is($artist->cds->count, 1, 'One CD created for artist');
69 is($artist->cds->first->title, 'Music to code by', 'CD created correctly');
70 is($artist->cds->first->tags->count, 1, 'One tag created for CD');
71 is($artist->cds->first->tags->first->tag, 'rock', 'Tag created correctly');
72
73 # Create via update - add a new CD
74 $artist->update({
75 cds => [ $artist->cds,
76 { title => 'Yet another CD',
77 year => 2006,
78 },
79 ],
80 });
81 is(($artist->cds->search({}, { order_by => 'year' }))[0]->title, 'Yet another CD', 'Updated and added another CD');
82
83 my $newartist = $schema->resultset('Artist')->find_or_create({ name => 'Fred 2'});
84
85 is($newartist->name, 'Fred 2', 'Retrieved the artist');
86};
87diag $@ if $@;
88
51f30f72 89# create over > 1 levels of might_have (A => { might_have => { B => has_many => C } } )
90eval {
91 my $artist = $schema->resultset('Artist')->first;
92 my $cd = $schema->resultset('CD')->create ({
93 artist => $artist,
94 title => 'Music to code by at night',
95 year => 2008,
96 tracks => [
97 {
98 position => 1,
99 title => 'Off by one again',
100 },
101 {
102 position => 2,
103 title => 'The dereferencer',
104 cd_single => {
105 artist => $artist,
106 year => 2008,
107 title => 'Was that a null (Single)',
108 tracks => [
109 { title => 'The dereferencer', position => 1 },
110 { title => 'The dereferencer II', position => 2 },
111 ],
112 cd_to_producer => [
113 {
114 producer => {
115 name => 'K&R',
116 }
117 }
118 ]
119 },
120 },
121 ],
122 });
123
124 isa_ok ($cd, 'DBICTest::CD', 'Main CD object created');
125 is ($cd->title, 'Music to code by at night', 'Correct CD title');
126 is ($cd->tracks->count, 2, 'Two tracks on main CD');
127
128 my ($t1, $t2) = $cd->tracks->all;
129 is ($t1->title, 'Off by one again', 'Correct 1st track name');
130 is ($t1->cd_single, undef, 'No single for 1st track');
131 is ($t2->title, 'The dereferencer', 'Correct 2nd track name');
132 isa_ok ($t2->cd_single, 'DBICTest::CD', 'Created a single for 2nd track');
133
134 my $single = $t2->cd_single;
135 is ($single->tracks->count, 2, 'Two tracks on single CD');
136 is ($single->tracks->find ({ position => 1})->title, 'The dereferencer', 'Correct 1st track title');
137 is ($single->tracks->find ({ position => 2})->title, 'The dereferencer II', 'Correct 2nd track title');
138
139 is ($single->cd_to_producer->count, 1, 'One producer created with the single cd');
140 is ($single->cd_to_producer->first->producer->name, 'K&R', 'Producer name correct');
141};
142diag $@ if $@;
143
04ec3909 144# nested find_or_create
145eval {
146 my $newartist2 = $schema->resultset('Artist')->find_or_create({
147 name => 'Fred 3',
148 cds => [
149 {
150 title => 'Noah Act',
151 year => 2007,
152 },
153 ],
154 });
155 is($newartist2->name, 'Fred 3', 'Created new artist with cds via find_or_create');
156};
157diag $@ if $@;
158
159# multiple same level has_many create
160eval {
161 my $artist2 = $schema->resultset('Artist')->create({
51f30f72 162 name => 'Fred 4',
04ec3909 163 cds => [
164 {
165 title => 'Music to code by',
166 year => 2007,
167 },
168 ],
169 cds_unordered => [
170 {
171 title => 'Music to code by',
172 year => 2007,
173 },
174 ]
175 });
176
177 is($artist2->in_storage, 1, 'artist with duplicate rels inserted okay');
178};
179diag $@ if $@;
3d8ee6ab 180
04ec3909 181# first create_related pass
182eval {
3d8ee6ab 183 my $artist = $schema->resultset('Artist')->first;
184
185 my $cd_result = $artist->create_related('cds', {
186
187 title => 'TestOneCD1',
188 year => 2007,
189 tracks => [
190
191 { position=>111,
192 title => 'TrackOne',
193 },
194 { position=>112,
195 title => 'TrackTwo',
196 }
197 ],
198
199 });
200
201 ok( $cd_result && ref $cd_result eq 'DBICTest::CD', "Got Good CD Class");
202 ok( $cd_result->title eq "TestOneCD1", "Got Expected Title");
203
204 my $tracks = $cd_result->tracks;
205
206 ok( ref $tracks eq "DBIx::Class::ResultSet", "Got Expected Tracks ResultSet");
207
208 foreach my $track ($tracks->all)
209 {
210 ok( $track && ref $track eq 'DBICTest::Track', 'Got Expected Track Class');
211 }
04ec3909 212};
213diag $@ if $@;
3d8ee6ab 214
04ec3909 215# second create_related with same arguments
216eval {
2ec8e594 217 my $artist = $schema->resultset('Artist')->first;
3d8ee6ab 218
2ec8e594 219 my $cd_result = $artist->create_related('cds', {
3d8ee6ab 220
2ec8e594 221 title => 'TestOneCD2',
3d8ee6ab 222 year => 2007,
223 tracks => [
224
225 { position=>111,
226 title => 'TrackOne',
227 },
228 { position=>112,
229 title => 'TrackTwo',
230 }
231 ],
232
9c6d6d93 233 liner_notes => { notes => 'I can haz liner notes?' },
234
3d8ee6ab 235 });
236
237 ok( $cd_result && ref $cd_result eq 'DBICTest::CD', "Got Good CD Class");
2ec8e594 238 ok( $cd_result->title eq "TestOneCD2", "Got Expected Title");
9c6d6d93 239 ok( $cd_result->notes eq 'I can haz liner notes?', 'Liner notes');
3d8ee6ab 240
241 my $tracks = $cd_result->tracks;
242
243 ok( ref $tracks eq "DBIx::Class::ResultSet", "Got Expected Tracks ResultSet");
244
245 foreach my $track ($tracks->all)
246 {
247 ok( $track && ref $track eq 'DBICTest::Track', 'Got Expected Track Class');
248 }
04ec3909 249};
250diag $@ if $@;
e5dddc05 251
04ec3909 252# create of parents of a record linker table
253eval {
254 my $cdp = $schema->resultset('CD_to_Producer')->create({
255 cd => { artist => 1, title => 'foo', year => 2000 },
256 producer => { name => 'jorge' }
257 });
258 ok($cdp, 'join table record created ok');
259};
260diag $@ if $@;
2bc3c81e 261
04ec3909 262#SPECIAL_CASE
263eval {
2bc3c81e 264 my $kurt_cobain = { name => 'Kurt Cobain' };
265
266 my $in_utero = $schema->resultset('CD')->new({
267 title => 'In Utero',
268 year => 1993
269 });
270
271 $kurt_cobain->{cds} = [ $in_utero ];
272
273
274 $schema->resultset('Artist')->populate([ $kurt_cobain ]); # %)
275 $a = $schema->resultset('Artist')->find({name => 'Kurt Cobain'});
276
277 is($a->name, 'Kurt Cobain', 'Artist insertion ok');
278 is($a->cds && $a->cds->first && $a->cds->first->title,
279 'In Utero', 'CD insertion ok');
04ec3909 280};
281diag $@ if $@;
2bc3c81e 282
04ec3909 283#SPECIAL_CASE2
284eval {
2bc3c81e 285 my $pink_floyd = { name => 'Pink Floyd' };
286
287 my $the_wall = { title => 'The Wall', year => 1979 };
288
289 $pink_floyd->{cds} = [ $the_wall ];
290
291
292 $schema->resultset('Artist')->populate([ $pink_floyd ]); # %)
293 $a = $schema->resultset('Artist')->find({name => 'Pink Floyd'});
294
295 is($a->name, 'Pink Floyd', 'Artist insertion ok');
296 is($a->cds && $a->cds->first->title, 'The Wall', 'CD insertion ok');
04ec3909 297};
298diag $@ if $@;
e02b9964 299
300## Create foreign key col obj including PK
301## See test 20 in 66relationships.t
04ec3909 302eval {
303 my $new_cd_hashref = {
304 cdid => 27,
305 title => 'Boogie Woogie',
306 year => '2007',
307 artist => { artistid => 17, name => 'king luke' }
308 };
e02b9964 309
04ec3909 310 my $cd = $schema->resultset("CD")->find(1);
f10ac17d 311
04ec3909 312 is($cd->artist->id, 1, 'rel okay');
f10ac17d 313
04ec3909 314 my $new_cd = $schema->resultset("CD")->create($new_cd_hashref);
315 is($new_cd->artist->id, 17, 'new id retained okay');
316};
317diag $@ if $@;
6ede9177 318
319eval {
320 $schema->resultset("CD")->create({
38c03c20 321 cdid => 28,
370f2ba2 322 title => 'Boogie Wiggle',
38c03c20 323 year => '2007',
324 artist => { artistid => 18, name => 'larry' }
6ede9177 325 });
38c03c20 326};
6ede9177 327is($@, '', 'new cd created without clash on related artist');
38c03c20 328
f10ac17d 329# Make sure exceptions from errors in created rels propogate
330eval {
370f2ba2 331 my $t = $schema->resultset("Track")->new({ cd => { artist => undef } });
332 #$t->cd($t->new_related('cd', { artist => undef } ) );
333 #$t->{_rel_in_storage} = 0;
f10ac17d 334 $t->insert;
335};
336like($@, qr/cd.artist may not be NULL/, "Exception propogated properly");
bbbf67eb 337
338# Test multi create over many_to_many
04ec3909 339eval {
340 $schema->resultset('CD')->create ({
341 artist => {
342 name => 'larry', # should already exist
343 },
76b8cf98 344 title => 'Warble Marble',
345 year => '2009',
346 cd_to_producer => [
04ec3909 347 { producer => { name => 'Cowboy Neal' } },
76b8cf98 348 ],
04ec3909 349 });
76b8cf98 350
04ec3909 351 my $m2m_cd = $schema->resultset('CD')->search ({ title => 'Warble Marble'});
352 is ($m2m_cd->count, 1, 'One CD row created via M2M create');
353 is ($m2m_cd->first->producers->count, 1, 'CD row created with one producer');
354 is ($m2m_cd->first->producers->first->name, 'Cowboy Neal', 'Correct producer row created');
355};
76b8cf98 356
357# and some insane multicreate
358# (should work, despite the fact that no one will probably use it this way)
359
04ec3909 360# first count how many rows do we initially have
76b8cf98 361my $counts;
04ec3909 362$counts->{$_} = $schema->resultset($_)->count for qw/Artist CD Genre Producer Tag/;
76b8cf98 363
364# do the crazy create
04ec3909 365eval {
366 $schema->resultset('CD')->create ({
367 artist => {
533292a0 368 name => 'james',
04ec3909 369 },
76b8cf98 370 title => 'Greatest hits 1',
371 year => '2012',
372 genre => {
373 name => '"Greatest" collections',
374 },
04ec3909 375 tags => [
376 { tag => 'A' },
377 { tag => 'B' },
378 ],
76b8cf98 379 cd_to_producer => [
380 {
381 producer => {
533292a0 382 name => 'bob',
76b8cf98 383 producer_to_cd => [
384 {
385 cd => {
386 artist => {
533292a0 387 name => 'lars',
04ec3909 388 cds => [
389 {
533292a0 390 title => 'Greatest hits 2',
04ec3909 391 year => 2012,
392 genre => {
393 name => '"Greatest" collections',
394 },
395 tags => [
396 { tag => 'A' },
397 { tag => 'B' },
398 ],
533292a0 399 # This cd is created via artist so it doesn't know about producers
400 cd_to_producer => [
401 # if we specify 'bob' here things bomb
402 # as the producer attached to Greatest Hits 1 is
403 # already created, but not yet inserted.
404 # Maybe this can be fixed, but things are hairy
405 # enough already.
406 #
407 #{ producer => { name => 'bob' } },
408 { producer => { name => 'paul' } },
409 { producer => {
410 name => 'flemming',
411 producer_to_cd => [
412 { cd => {
413 artist => {
414 name => 'kirk',
415 cds => [
416 {
417 title => 'Greatest hits 3',
418 year => 2012,
419 genre => {
420 name => '"Greatest" collections',
421 },
422 tags => [
423 { tag => 'A' },
424 { tag => 'B' },
425 ],
426 },
427 {
428 title => 'Greatest hits 4',
429 year => 2012,
430 genre => {
431 name => '"Greatest" collections2',
432 },
433 tags => [
434 { tag => 'A' },
435 { tag => 'B' },
436 ],
437 },
438 ],
439 },
440 title => 'Greatest hits 5',
441 year => 2013,
442 genre => {
443 name => '"Greatest" collections2',
444 },
445 }},
446 ],
447 }},
448 ],
04ec3909 449 },
450 ],
76b8cf98 451 },
533292a0 452 title => 'Greatest hits 6',
76b8cf98 453 year => 2012,
454 genre => {
455 name => '"Greatest" collections',
456 },
04ec3909 457 tags => [
458 { tag => 'A' },
459 { tag => 'B' },
460 ],
76b8cf98 461 },
462 },
463 {
464 cd => {
465 artist => {
533292a0 466 name => 'lars', # should already exist
467 # even though the artist 'name' is not uniquely constrained
468 # find_or_create will arguably DWIM
76b8cf98 469 },
533292a0 470 title => 'Greatest hits 7',
471 year => 2013,
76b8cf98 472 },
473 },
474 ],
475 },
476 },
477 ],
04ec3909 478 });
76b8cf98 479
533292a0 480 is ($schema->resultset ('Artist')->count, $counts->{Artist} + 3, '3 new artists created');
481 is ($schema->resultset ('Genre')->count, $counts->{Genre} + 2, '2 additional genres created');
482 is ($schema->resultset ('Producer')->count, $counts->{Producer} + 3, '3 new producer');
483 is ($schema->resultset ('CD')->count, $counts->{CD} + 7, '7 new CDs');
484 is ($schema->resultset ('Tag')->count, $counts->{Tag} + 10, '10 new Tags');
485
486 my $cd_rs = $schema->resultset ('CD')
487 ->search ({ title => { -like => 'Greatest hits %' }}, { order_by => 'title'} );
488 is ($cd_rs->count, 7, '7 greatest hits created');
489
490 my $cds_2012 = $cd_rs->search ({ year => 2012});
491 is ($cds_2012->count, 5, '5 CDs created in 2012');
492
493 is (
494 $cds_2012->search(
495 { 'tags.tag' => { -in => [qw/A B/] } },
496 { join => 'tags', group_by => 'me.cdid' }
497 ),
498 5,
c45f4e10 499 'All 10 tags were pairwise distributed between 5 year-2012 CDs'
533292a0 500 );
501
502 my $paul_prod = $cd_rs->search (
503 { 'producer.name' => 'paul'},
504 { join => { cd_to_producer => 'producer' } }
505 );
506 is ($paul_prod->count, 1, 'Paul had 1 production');
507 my $pauls_cd = $paul_prod->single;
508 is ($pauls_cd->cd_to_producer->count, 2, 'Paul had one co-producer');
509 is (
510 $pauls_cd->search_related ('cd_to_producer',
511 { 'producer.name' => 'flemming'},
512 { join => 'producer' }
513 )->count,
514 1,
515 'The second producer is flemming',
516 );
517
518 my $kirk_cds = $cd_rs->search ({ 'artist.name' => 'kirk' }, { join => 'artist' });
519 is ($kirk_cds, 3, 'Kirk had 3 CDs');
520 is (
521 $kirk_cds->search (
522 { 'cd_to_producer.cd' => { '!=', undef } },
523 { join => 'cd_to_producer' },
524 ),
525 1,
526 'Kirk had a producer only on one cd',
527 );
528
529 my $lars_cds = $cd_rs->search ({ 'artist.name' => 'lars' }, { join => 'artist' });
530 is ($lars_cds->count, 3, 'Lars had 3 CDs');
531 is (
532 $lars_cds->search (
533 { 'cd_to_producer.cd' => undef },
534 { join => 'cd_to_producer' },
535 ),
536 0,
537 'Lars always had a producer',
538 );
539 is (
540 $lars_cds->search_related ('cd_to_producer',
541 { 'producer.name' => 'flemming'},
542 { join => 'producer' }
543 )->count,
544 1,
545 'Lars produced 1 CD with flemming',
546 );
547 is (
548 $lars_cds->search_related ('cd_to_producer',
549 { 'producer.name' => 'bob'},
550 { join => 'producer' }
551 )->count,
552 2,
553 'Lars produced 2 CDs with bob',
554 );
555
556 my $bob_prod = $cd_rs->search (
557 { 'producer.name' => 'bob'},
558 { join => { cd_to_producer => 'producer' } }
559 );
560 is ($bob_prod->count, 3, 'Bob produced a total of 3 CDs');
561
562 is (
563 $bob_prod->search ({ 'artist.name' => 'james' }, { join => 'artist' })->count,
564 1,
c45f4e10 565 "Bob produced james' only CD",
533292a0 566 );
04ec3909 567};
568diag $@ if $@;