File: 66relationship.t

package info (click to toggle)
libdbix-class-perl 0.08010-2
  • links: PTS, VCS
  • area: main
  • in suites: lenny
  • size: 2,052 kB
  • ctags: 1,064
  • sloc: perl: 10,536; sql: 225; makefile: 45
file content (245 lines) | stat: -rwxr-xr-x 9,909 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
use strict;
use warnings;  

use Test::More;
use lib qw(t/lib);
use DBICTest;

my $schema = DBICTest->init_schema();

plan tests => 62;

# has_a test
my $cd = $schema->resultset("CD")->find(4);
my ($artist) = ($INC{'DBICTest/HelperRels'}
                  ? $cd->artist
                  : $cd->search_related('artist'));
is($artist->name, 'Random Boy Band', 'has_a search_related ok');

# has_many test with an order_by clause defined
$artist = $schema->resultset("Artist")->find(1);
my @cds = ($INC{'DBICTest/HelperRels'}
             ? $artist->cds
             : $artist->search_related('cds'));
is( $cds[1]->title, 'Spoonful of bees', 'has_many search_related with order_by ok' );

# search_related with additional abstract query
@cds = ($INC{'DBICTest/HelperRels'}
          ? $artist->cds({ title => { like => '%of%' } })
          : $artist->search_related('cds', { title => { like => '%of%' } } )
       );
is( $cds[1]->title, 'Forkful of bees', 'search_related with abstract query ok' );

# creating a related object
if ($INC{'DBICTest/HelperRels.pm'}) {
  $artist->add_to_cds({ title => 'Big Flop', year => 2005 });
} else {
  $artist->create_related( 'cds', {
      title => 'Big Flop',
      year => 2005,
  } );
}

is( ($artist->search_related('cds'))[3]->title, 'Big Flop', 'create_related ok' );

my( $rs_from_list ) = $artist->search_related_rs('cds');
is( ref($rs_from_list), 'DBIx::Class::ResultSet', 'search_related_rs in list context returns rs' );

( $rs_from_list ) = $artist->cds_rs();
is( ref($rs_from_list), 'DBIx::Class::ResultSet', 'relation_rs in list context returns rs' );

# count_related
is( $artist->count_related('cds'), 4, 'count_related ok' );

# set_from_related
my $track = $schema->resultset("Track")->create( {
  trackid => 1,
  cd => 3,
  position => 98,
  title => 'Hidden Track'
} );
$track->set_from_related( cd => $cd );

is($track->disc->cdid, 4, 'set_from_related ok, including alternative accessor' );

$track->set_from_related( cd => undef );

ok( !defined($track->cd), 'set_from_related with undef ok');


# update_from_related, the same as set_from_related, but it calls update afterwards
$track = $schema->resultset("Track")->create( {
  trackid => 2,
  cd => 3,
  position => 99,
  title => 'Hidden Track 2'
} );
$track->update_from_related( cd => $cd );

my $t_cd = ($schema->resultset("Track")->search( cd => 4, position => 99 ))[0]->cd;

is( $t_cd->cdid, 4, 'update_from_related ok' );

# find_or_create_related with an existing record
$cd = $artist->find_or_create_related( 'cds', { title => 'Big Flop' } );
is( $cd->year, 2005, 'find_or_create_related on existing record ok' );

# find_or_create_related creating a new record
$cd = $artist->find_or_create_related( 'cds', {
  title => 'Greatest Hits',
  year => 2006,
} );
is( $cd->title, 'Greatest Hits', 'find_or_create_related new record ok' );

@cds = $artist->search_related('cds');
is( ($artist->search_related('cds'))[4]->title, 'Greatest Hits', 'find_or_create_related new record search ok' );

$artist->delete_related( cds => { title => 'Greatest Hits' });
cmp_ok( $schema->resultset("CD")->search( title => 'Greatest Hits' ), '==', 0, 'delete_related ok' );

# find_or_new_related with an existing record
$cd = $artist->find_or_new_related( 'cds', { title => 'Big Flop' } );
is( $cd->year, 2005, 'find_or_new_related on existing record ok' );
ok( $cd->in_storage, 'find_or_new_related on existing record: is in_storage' );

# find_or_new_related instantiating a new record
$cd = $artist->find_or_new_related( 'cds', {
  title => 'Greatest Hits 2: Louder Than Ever',
  year => 2007,
} );
is( $cd->title, 'Greatest Hits 2: Louder Than Ever', 'find_or_new_related new record ok' );
ok( ! $cd->in_storage, 'find_or_new_related on a new record: not in_storage' );

# print STDERR Data::Dumper::Dumper($cd->get_columns);
# $cd->result_source->schema->storage->debug(1);
$cd->artist(undef);
my $newartist = $cd->find_or_new_related( 'artist', {
  name => 'Random Boy Band Two',
  artistid => 200,
} );
# $cd->result_source->schema->storage->debug(0);
is($newartist->name, 'Random Boy Band Two', 'find_or_new_related new artist record with id');
is($newartist->id, 200, 'find_or_new_related new artist id set');

SKIP: {
  skip "relationship checking needs fixing", 1;
  # try to add a bogus relationship using the wrong cols
  eval {
      DBICTest::Schema::Artist->add_relationship(
          tracks => 'DBICTest::Schema::Track',
          { 'foreign.cd' => 'self.cdid' }
      );
  };
  like($@, qr/Unknown column/, 'failed when creating a rel with invalid key, ok');
}
  
# another bogus relationship using no join condition
eval {
    DBICTest::Schema::Artist->add_relationship( tracks => 'DBICTest::Track' );
};
like($@, qr/join condition/, 'failed when creating a rel without join condition, ok');

# many_to_many helper tests
$cd = $schema->resultset("CD")->find(1);
my @producers = $cd->producers();
is( $producers[0]->name, 'Matt S Trout', 'many_to_many ok' );
is( $cd->producers_sorted->next->name, 'Bob The Builder',
    'sorted many_to_many ok' );
is( $cd->producers_sorted(producerid => 3)->next->name, 'Fred The Phenotype',
    'sorted many_to_many with search condition ok' );

$cd = $schema->resultset('CD')->find(2);
my $prod_rs = $cd->producers();
my $prod_before_count = $schema->resultset('Producer')->count;
is( $prod_rs->count, 0, "CD doesn't yet have any producers" );
my $prod = $schema->resultset('Producer')->find(1);
$cd->add_to_producers($prod);
is( $prod_rs->count(), 1, 'many_to_many add_to_$rel($obj) count ok' );
is( $prod_rs->first->name, 'Matt S Trout',
    'many_to_many add_to_$rel($obj) ok' );
$cd->remove_from_producers($prod);
is( $schema->resultset('Producer')->find(1)->name, 'Matt S Trout',
    "producer object exists after remove of link" );
is( $prod_rs->count, 0, 'many_to_many remove_from_$rel($obj) ok' );
$cd->add_to_producers({ name => 'Testy McProducer' });
is( $schema->resultset('Producer')->count, $prod_before_count+1,
    'add_to_$rel($hash) inserted a new producer' );
is( $prod_rs->count(), 1, 'many_to_many add_to_$rel($hash) count ok' );
is( $prod_rs->first->name, 'Testy McProducer',
    'many_to_many add_to_$rel($hash) ok' );
$cd->add_to_producers({ name => 'Jack Black' });
is( $prod_rs->count(), 2, 'many_to_many add_to_$rel($hash) count ok' );
$cd->set_producers($schema->resultset('Producer')->all);
is( $cd->producers->count(), $prod_before_count+2, 
    'many_to_many set_$rel(@objs) count ok' );
$cd->set_producers($schema->resultset('Producer')->find(1));
is( $cd->producers->count(), 1, 'many_to_many set_$rel($obj) count ok' );
$cd->set_producers([$schema->resultset('Producer')->all]);
is( $cd->producers->count(), $prod_before_count+2, 
    'many_to_many set_$rel(\@objs) count ok' );
$cd->set_producers([$schema->resultset('Producer')->find(1)]);
is( $cd->producers->count(), 1, 'many_to_many set_$rel([$obj]) count ok' );

eval { $cd->remove_from_producers({ fake => 'hash' }); };
like( $@, qr/needs an object/, 'remove_from_$rel($hash) dies correctly' );

eval { $cd->add_to_producers(); };
like( $@, qr/needs an object or hashref/,
      'add_to_$rel(undef) dies correctly' );

# many_to_many stresstest
my $twokey = $schema->resultset('TwoKeys')->find(1,1);
my $fourkey = $schema->resultset('FourKeys')->find(1,2,3,4);

is( $twokey->fourkeys->count, 0, 'twokey has no fourkeys' );
$twokey->add_to_fourkeys($fourkey, { autopilot => 'engaged' });
my $got_fourkey = $twokey->fourkeys({ sensors => 'online' })->first;
is( $twokey->fourkeys->count, 1, 'twokey has one fourkey' );
is( $got_fourkey->$_, $fourkey->$_,
    'fourkeys row has the correct value for column '.$_ )
  for (qw(foo bar hello goodbye sensors));
$twokey->remove_from_fourkeys($fourkey);
is( $twokey->fourkeys->count, 0, 'twokey has no fourkeys' );
is( $twokey->fourkeys_to_twokeys->count, 0,
    'twokey has no links to fourkey' );

my $undef_artist_cd = $schema->resultset("CD")->new_result({ 'title' => 'badgers', 'year' => 2007 });
is($undef_artist_cd->has_column_loaded('artist'), '', 'FK not loaded');
is($undef_artist_cd->search_related('artist')->count, 3, 'open search on undef FK');

my $def_artist_cd = $schema->resultset("CD")->new_result({ 'title' => 'badgers', 'year' => 2007, artist => undef });
is($def_artist_cd->has_column_loaded('artist'), 1, 'FK loaded');
is($def_artist_cd->search_related('artist')->count, 0, 'closed search on null FK');

# test undirected many-to-many relationship (e.g. "related artists")
my $undir_maps = $schema->resultset("Artist")->find(1)->artist_undirected_maps;
is($undir_maps->count, 1, 'found 1 undirected map for artist 1');

$undir_maps = $schema->resultset("Artist")->find(2)->artist_undirected_maps;
is($undir_maps->count, 1, 'found 1 undirected map for artist 2');

my $mapped_rs = $undir_maps->search_related('mapped_artists');

my @art = $mapped_rs->all;

cmp_ok(@art, '==', 2, "Both artist returned from map");

my $searched = $mapped_rs->search({'mapped_artists.artistid' => {'!=', undef}});

cmp_ok($searched->count, '==', 2, "Both artist returned from map after adding another condition");

# check join through cascaded has_many relationships
$artist = $schema->resultset("Artist")->find(1);
my $trackset = $artist->cds->search_related('tracks');
# LEFT join means we also see the trackless additional album...
cmp_ok($trackset->count, '==', 11, "Correct number of tracks for artist");

# now see about updating eveything that belongs to artist 2 to artist 3
$artist = $schema->resultset("Artist")->find(2);
my $nartist = $schema->resultset("Artist")->find(3);
cmp_ok($artist->cds->count, '==', 1, "Correct orig #cds for artist");
cmp_ok($nartist->cds->count, '==', 1, "Correct orig #cds for artist");
$artist->cds->update({artist => $nartist->id});
cmp_ok($artist->cds->count, '==', 0, "Correct new #cds for artist");
cmp_ok($nartist->cds->count, '==', 2, "Correct new #cds for artist");