Commit | Line | Data |
c0e7b4e5 |
1 | package # hide from PAUSE |
2 | DBIx::Class::Relationship::HasOne; |
22b15c96 |
3 | |
4 | use strict; |
5 | use warnings; |
70c28808 |
6 | use DBIx::Class::Carp; |
ed7ab0f4 |
7 | use Try::Tiny; |
fd323bf1 |
8 | use namespace::clean; |
22b15c96 |
9 | |
fd323bf1 |
10 | our %_pod_inherit_config = |
044e70c7 |
11 | ( |
12 | class_map => { 'DBIx::Class::Relationship::HasOne' => 'DBIx::Class::Relationship' } |
13 | ); |
14 | |
07037f89 |
15 | sub might_have { |
16 | shift->_has_one('LEFT' => @_); |
17 | } |
18 | |
22b15c96 |
19 | sub has_one { |
e5d98edd |
20 | shift->_has_one(undef() => @_); |
07037f89 |
21 | } |
22 | |
23 | sub _has_one { |
503536d5 |
24 | my ($class, $join_type, $rel, $f_class, $cond, $attrs) = @_; |
99be059e |
25 | unless (ref $cond) { |
0b0743af |
26 | my $pri = $class->result_source_instance->_single_pri_col_or_die; |
e36de82e |
27 | |
9e7525a2 |
28 | my ($f_key,$guess,$f_rsrc); |
dcf8330b |
29 | if (defined $cond && length $cond) { |
99be059e |
30 | $f_key = $cond; |
dcf8330b |
31 | $guess = "caller specified foreign key '$f_key'"; |
22b15c96 |
32 | } |
9e7525a2 |
33 | else { |
34 | # at this point we need to load the foreigner, expensive or not |
35 | $class->ensure_class_loaded($f_class); |
36 | |
37 | $f_rsrc = try { |
38fe1ff9 |
38 | my $r = $f_class->result_source_instance; |
39 | die "There got to be some columns by now... (exception caught and rewritten by catch below)" |
40 | unless $r->columns; |
41 | $r; |
9e7525a2 |
42 | } |
43 | catch { |
44 | $class->throw_exception( |
45 | "Foreign class '$f_class' does not seem to be a Result class " |
46 | . "(or it simply did not load entirely due to a circular relation chain)" |
47 | ); |
48 | }; |
0b0743af |
49 | |
9e7525a2 |
50 | if ($f_rsrc->has_column($rel)) { |
51 | $f_key = $rel; |
52 | $guess = "using given relationship name '$rel' as foreign key column name"; |
53 | } |
54 | else { |
55 | $f_key = $f_rsrc->_single_pri_col_or_die; |
56 | $guess = "using primary key of foreign class for foreign key"; |
57 | } |
58 | } |
59 | |
38fe1ff9 |
60 | # FIXME - this check needs to be moved to schema-composition time... |
61 | # # only perform checks if the far side was not preloaded above *AND* |
62 | # # appears to have been loaded by something else (has a rsrc_instance) |
63 | # if (! $f_rsrc and $f_rsrc = try { $f_class->result_source_instance }) { |
64 | # $class->throw_exception( |
65 | # "No such column '$f_key' on foreign class ${f_class} ($guess)" |
66 | # ) if !$f_rsrc->has_column($f_key); |
67 | # } |
0b0743af |
68 | |
503536d5 |
69 | $cond = { "foreign.${f_key}" => "self.${pri}" }; |
07037f89 |
70 | } |
2339d6c7 |
71 | $class->_validate_has_one_condition($cond); |
edcecdbb |
72 | |
73 | my $default_cascade = ref $cond eq 'CODE' ? 0 : 1; |
74 | |
07037f89 |
75 | $class->add_relationship($rel, $f_class, |
76 | $cond, |
503536d5 |
77 | { accessor => 'single', |
edcecdbb |
78 | cascade_update => $default_cascade, |
79 | cascade_delete => $default_cascade, |
07037f89 |
80 | ($join_type ? ('join_type' => $join_type) : ()), |
503536d5 |
81 | %{$attrs || {}} }); |
07037f89 |
82 | 1; |
22b15c96 |
83 | } |
84 | |
2339d6c7 |
85 | sub _validate_has_one_condition { |
dc571b76 |
86 | my ($class, $cond ) = @_; |
87 | |
88 | return if $ENV{DBIC_DONT_VALIDATE_RELS}; |
89 | return unless 'HASH' eq ref $cond; |
90 | foreach my $foreign_id ( keys %$cond ) { |
91 | my $self_id = $cond->{$foreign_id}; |
92 | |
93 | # we can ignore a bad $self_id because add_relationship handles this |
6909ab3c |
94 | # exception |
dc571b76 |
95 | return unless $self_id =~ /^self\.(.*)$/; |
6909ab3c |
96 | |
dc571b76 |
97 | my $key = $1; |
e705f529 |
98 | $class->throw_exception("Defining rel on ${class} that includes '$key' but no such column defined here yet") |
2339d6c7 |
99 | unless $class->has_column($key); |
dc571b76 |
100 | my $column_info = $class->column_info($key); |
101 | if ( $column_info->{is_nullable} ) { |
416e0bc0 |
102 | carp(qq'"might_have/has_one" must not be on columns with is_nullable set to true ($class/$key). This might indicate an incorrect use of those relationship helpers instead of belongs_to.'); |
dc571b76 |
103 | } |
104 | } |
105 | } |
106 | |
22b15c96 |
107 | 1; |