Allow coderef maps to call back into the hashref mapping code
[dbsrgits/DBIx-Class-Schema-Loader.git] / t / 45relationships.t
CommitLineData
c8c27020 1use strict;
7b6a8d73 2use Test::More;
c8c27020 3use Test::Exception;
7b6a8d73 4use Try::Tiny;
c8c27020 5use lib qw(t/lib);
6use make_dbictest_db;
7
8use DBIx::Class::Schema::Loader;
9
59388920 10my $schema_counter = 0;
11
c8c27020 12# test skip_relationships
13my $regular = schema_with();
14is( ref($regular->source('Bar')->relationship_info('fooref')), 'HASH',
15 'regularly-made schema has fooref rel',
16 );
17my $skip_rel = schema_with( skip_relationships => 1 );
18is_deeply( $skip_rel->source('Bar')->relationship_info('fooref'), undef,
19 'skip_relationships blocks generation of fooref rel',
20 );
21
59388920 22# test hashref as rel_name_map
23my $hash_relationship = schema_with(
24 rel_name_map => {
25 fooref => "got_fooref",
26 bars => "ignored",
27 Foo => {
28 bars => "got_bars",
29 fooref => "ignored",
30 },
31 }
32);
33is( ref($hash_relationship->source('Foo')->relationship_info('got_bars')),
34 'HASH',
35 'single level hash in rel_name_map picked up correctly'
36 );
37is( ref($hash_relationship->source('Bar')->relationship_info('got_fooref')),
38 'HASH',
39 'double level hash in rel_name_map picked up correctly'
40 );
41
42# test coderef as rel_name_map
43my $code_relationship = schema_with(
44 rel_name_map => sub {
c4d629ab 45 my ($args, $orig) = @_;
59388920 46
47 if ($args->{local_moniker} eq 'Foo') {
48 is_deeply(
49 $args,
50 {
51 name => 'bars',
52 type => 'has_many',
53 local_class =>
54 "DBICTest::Schema::${schema_counter}::Result::Foo",
55 local_moniker => 'Foo',
56 local_columns => ['fooid'],
57 remote_class =>
58 "DBICTest::Schema::${schema_counter}::Result::Bar",
59 remote_moniker => 'Bar',
60 remote_columns => ['fooref'],
61 },
62 'correct args for Foo passed'
63 );
59388920 64 }
65 elsif ($args->{local_moniker} eq 'Bar') {
66 is_deeply(
67 $args,
68 {
69 name => 'fooref',
70 type => 'belongs_to',
71 local_class =>
72 "DBICTest::Schema::${schema_counter}::Result::Bar",
73 local_moniker => 'Bar',
74 local_columns => ['fooref'],
75 remote_class =>
76 "DBICTest::Schema::${schema_counter}::Result::Foo",
77 remote_moniker => 'Foo',
78 remote_columns => ['fooid'],
79 },
80 'correct args for Foo passed'
81 );
59388920 82 }
c4d629ab 83 else {
84 fail( 'correct args passed to rel_name_map' );
85 diag "args were: ", explain $args;
86 }
87 return $orig->({
88 Bar => { fooref => 'fooref_caught' },
89 Foo => { bars => 'bars_caught' },
90 });
59388920 91 }
92 );
93is( ref($code_relationship->source('Foo')->relationship_info('bars_caught')),
94 'HASH',
95 'rel_name_map overrode local_info correctly'
96 );
97is( ref($code_relationship->source('Bar')->relationship_info('fooref_caught')),
98 'HASH',
99 'rel_name_map overrode remote_info correctly'
100 );
101
c4d629ab 102throws_ok {
103 schema_with( rel_name_map => sub { $_[-1]->(sub{}) } ),
104} qr/reentered rel_name_map must be a hashref/, 'throws error for invalid (code) rel_name_map callback map';
59388920 105
c8c27020 106
107# test relationship_attrs
108throws_ok {
109 schema_with( relationship_attrs => 'laughably invalid!!!' );
7b6a8d73 110} qr/relationship_attrs/, 'throws error for invalid (scalar) relationship_attrs';
c8c27020 111
7b6a8d73 112throws_ok {
113 schema_with( relationship_attrs => [qw/laughably invalid/] );
114} qr/relationship_attrs/, 'throws error for invalid (arrayref) relationship_attrs';
c8c27020 115
116{
117 my $nodelete = schema_with( relationship_attrs =>
118 {
119 all => { cascade_delete => 0 },
120 belongs_to => { cascade_delete => 1 },
121 },
122 );
123
124 my $bars_info = $nodelete->source('Foo')->relationship_info('bars');
125 #use Data::Dumper;
126 #die Dumper([ $nodelete->source('Foo')->relationships() ]);
127 my $fooref_info = $nodelete->source('Bar')->relationship_info('fooref');
128 is( ref($fooref_info), 'HASH',
129 'fooref rel is present',
130 );
131 is( $bars_info->{attrs}->{cascade_delete}, 0,
132 'relationship_attrs settings seem to be getting through to the generated rels',
133 );
134 is( $fooref_info->{attrs}->{cascade_delete}, 1,
135 'belongs_to in relationship_attrs overrides all def',
136 );
137}
138
7b6a8d73 139# test relationship_attrs coderef
140{
141 my $relationship_attrs_coderef_invoked = 0;
142 my $schema;
143
144 lives_ok {
145 $schema = schema_with(relationship_attrs => sub {
146 my %p = @_;
147
148 $relationship_attrs_coderef_invoked++;
149
150 if ($p{rel_name} eq 'bars') {
3492170f 151 is $p{rel_type}, 'has_many', 'correct rel_type';
7b6a8d73 152 is $p{local_table}, 'foo', 'correct local_table';
153 is_deeply $p{local_cols}, [ 'fooid' ], 'correct local_cols';
154 is $p{remote_table}, 'bar', 'correct remote_table';
155 is_deeply $p{remote_cols}, [ 'fooref' ], 'correct remote_cols';
156 is_deeply $p{attrs}, {
157 cascade_delete => 0,
158 cascade_copy => 0,
159 }, "got default rel attrs for $p{rel_name} in $p{local_table}";
160
161 like $p{local_source}->result_class,
162 qr/^DBICTest::Schema::\d+::Result::Foo\z/,
163 'correct local source';
164
165 like $p{remote_source}->result_class,
166 qr/^DBICTest::Schema::\d+::Result::Bar\z/,
167 'correct remote source';
168
169 $p{attrs}{snoopy} = 1;
170
171 return $p{attrs};
172 }
173 elsif ($p{rel_name} eq 'fooref') {
3492170f 174 is $p{rel_type}, 'belongs_to', 'correct rel_type';
7b6a8d73 175 is $p{local_table}, 'bar', 'correct local_table';
176 is_deeply $p{local_cols}, [ 'fooref' ], 'correct local_cols';
177 is $p{remote_table}, 'foo', 'correct remote_table';
178 is_deeply $p{remote_cols}, [ 'fooid' ], 'correct remote_cols';
179 is_deeply $p{attrs}, {
180 on_delete => 'NO ACTION',
181 on_update => 'NO ACTION',
182 is_deferrable => 0,
183 }, "got correct rel attrs for $p{rel_name} in $p{local_table}";
184
185 like $p{local_source}->result_class,
186 qr/^DBICTest::Schema::\d+::Result::Bar\z/,
187 'correct local source';
188
189 like $p{remote_source}->result_class,
190 qr/^DBICTest::Schema::\d+::Result::Foo\z/,
191 'correct remote source';
192
193 $p{attrs}{scooby} = 1;
194
195 return $p{attrs};
196 }
197 else {
198 fail "unknown rel $p{rel_name} in $p{local_table}";
199 }
200 });
201 } 'dumping schema with coderef relationship_attrs survived';
202
203 is $relationship_attrs_coderef_invoked, 2,
204 'relationship_attrs coderef was invoked correct number of times';
205
206 is ((try { $schema->source('Foo')->relationship_info('bars')->{attrs}{snoopy} }) || undef, 1,
207 "correct relationship attributes for 'bars' in 'Foo'");
208
209 is ((try { $schema->source('Bar')->relationship_info('fooref')->{attrs}{scooby} }) || undef, 1,
210 "correct relationship attributes for 'fooref' in 'Bar'");
211}
212
213done_testing;
214
c8c27020 215#### generates a new schema with the given opts every time it's called
c8c27020 216sub schema_with {
217 $schema_counter++;
218 DBIx::Class::Schema::Loader::make_schema_at(
219 'DBICTest::Schema::'.$schema_counter,
220 { naming => 'current', @_ },
221 [ $make_dbictest_db::dsn ],
222 );
223 "DBICTest::Schema::$schema_counter"->clone;
224}