Cleaner error message for using source() without required argument
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / ResultSourceHandle.pm
CommitLineData
aec3eff1 1package DBIx::Class::ResultSourceHandle;
2
3use strict;
4use warnings;
aec3eff1 5
6use base qw/DBIx::Class/;
7
4376a157 8use Storable qw/nfreeze thaw/;
9use DBIx::Class::Exception;
10use Try::Tiny;
11
12use namespace::clean;
13
aec3eff1 14use overload
3441fd57 15 q/""/ => sub { __PACKAGE__ . ":" . shift->source_moniker; },
aec3eff1 16 fallback => 1;
17
4376a157 18__PACKAGE__->mk_group_accessors('simple' => qw/schema source_moniker _detached_source/);
aec3eff1 19
4146e3da 20# Schema to use when thawing.
21our $thaw_schema;
22
aec3eff1 23=head1 NAME
24
4376a157 25DBIx::Class::ResultSourceHandle - Serializable pointers to ResultSource instances
aec3eff1 26
27=head1 DESCRIPTION
28
4376a157 29Currently instances of this class are used to allow proper serialization of
30L<ResultSources|DBIx::Class::ResultSource> (which may contain unserializable
31elements like C<CODE> references).
aec3eff1 32
4376a157 33Originally this module was used to remove the fixed link between
34L<Rows|DBIx::Class::Row>/L<ResultSets|DBIx::Class::ResultSet> and the actual
35L<result source objects|DBIx::Class::ResultSource> in order to obviate the need
36of keeping a L<schema instance|DBIx::Class::Schema> constantly in scope, while
37at the same time avoiding leaks due to circular dependencies. This is however
38no longer needed after introduction of a proper mutual-assured-destruction
39contract between a C<Schema> instance and its C<ResultSource> registrants.
aec3eff1 40
41=head1 METHODS
42
43=head2 new
44
45=cut
46
47sub new {
4376a157 48 my ($class, $args) = @_;
49 my $self = bless $args, ref $class || $class;
aec3eff1 50
4376a157 51 unless( ($self->{schema} || $self->{_detached_source}) && $self->{source_moniker} ) {
52 my $err = 'Expecting a schema instance and a source moniker';
53 $self->{schema}
54 ? $self->{schema}->throw_exception($err)
55 : DBIx::Class::Exception->throw($err)
56 }
aec3eff1 57
4376a157 58 $self;
aec3eff1 59}
60
61=head2 resolve
62
3441fd57 63Resolve the moniker into the actual ResultSource object
aec3eff1 64
65=cut
66
4376a157 67sub resolve {
68 return $_[0]->{schema}->source($_[0]->source_moniker) if $_[0]->{schema};
69
70 $_[0]->_detached_source || DBIx::Class::Exception->throw( sprintf (
71 # vague error message as this is never supposed to happen
72 "Unable to resolve moniker '%s' - please contact the dev team at %s",
73 $_[0]->source_moniker,
74 'http://search.cpan.org/dist/DBIx-Class/lib/DBIx/Class.pm#GETTING_HELP/SUPPORT',
75 ), 'full_stacktrace');
76}
aec3eff1 77
7137528d 78=head2 STORABLE_freeze
79
80Freezes a handle.
81
82=cut
83
aec3eff1 84sub STORABLE_freeze {
4376a157 85 my ($self, $cloning) = @_;
4146e3da 86
4376a157 87 my $to_serialize = { %$self };
d4daee7b 88
4376a157 89 delete $to_serialize->{schema};
90 delete $to_serialize->{_detached_source};
91 $to_serialize->{_frozen_from_class} = $self->{schema}
92 ? $self->{schema}->class($self->source_moniker)
93 : $self->{_detached_source}->result_class
94 ;
7cfda9a6 95
4376a157 96 nfreeze($to_serialize);
aec3eff1 97}
98
7137528d 99=head2 STORABLE_thaw
100
4146e3da 101Thaws frozen handle. Resets the internal schema reference to the package
48580715 102variable C<$thaw_schema>. The recommended way of setting this is to use
323e0bd0 103C<< $schema->thaw($ice) >> which handles this for you.
7137528d 104
105=cut
106
aec3eff1 107sub STORABLE_thaw {
4376a157 108 my ($self, $cloning, $ice) = @_;
109 %$self = %{ thaw($ice) };
110
111 my $from_class = delete $self->{_frozen_from_class};
112
113 if( $thaw_schema ) {
114 $self->schema( $thaw_schema );
115 }
116 elsif( my $rs = $from_class->result_source_instance ) {
117 # in the off-chance we are using CDBI-compat and have leaked $schema already
118 if( my $s = try { $rs->schema } ) {
119 $self->schema( $s );
3a81f59b 120 }
121 else {
4376a157 122 $rs->source_name( $self->source_moniker );
123 $rs->{_detached_thaw} = 1;
124 $self->_detached_source( $rs );
3a81f59b 125 }
4376a157 126 }
127 else {
128 DBIx::Class::Exception->throw(
129 "Thaw failed - original result class '$from_class' does not exist on this system"
130 );
131 }
aec3eff1 132}
133
4146e3da 134=head1 AUTHOR
135
136Ash Berlin C<< <ash@cpan.org> >>
137
138=cut
139
aec3eff1 1401;