[Dbix-class] Set a resultset_class for a result_class from within
a component loaded by the result_class
Peter Rabbitson
rabbit+dbic at rabbit.us
Thu Mar 5 18:02:13 GMT 2009
David Ihnen wrote:
> For these purposes I found this sneaky little ResultSetManager extension.
>
> You put ResultSetManager in your load_components and you put your custom
> plugin for resultset into a load_resultset_components call. An example
> from one of my classes.
Isn't ResultSetManager deprecated to the point of removal?
> Nothing is actually a plugin that impliments the 'Nothing' design
> pattern - that is - instead of returning null when referencing a row in
> an empty resultset (particularly ->single and ->first, which I use many
> times when NOT looping over results, hence resulting in undef
> dereference errors on empty) it instead returns a magical 'Nothing'
> object which has characteristics like - (->is_nothing === 1, ->id === 0,
> @list = $rs->method === (), $row = $rs->method === bless({}, Nothing).
Cool, I am not the only one who finds this cool and uses it lots :)
Here is my version if you are interested. File name is Null/Pattern.pm,
used by simply __PACKAGE__->load_components (qw/Null::Pattern/)
package DBIx::Class::Null;
use warnings;
use strict;
use Scalar::Util ();
use Carp ();
use overload (
'bool' => sub { 0 },
'""' => sub { '' },
'0+' => sub { 0 },
'+' => sub { $_[2] ? $_[1] || 0 : $_[2] || 0 },
'-' => sub { $_[2] ? $_[1] : - $_[1] },
'*' => sub { 0 },
'**' => sub { $_[2] ? 1 : 0 },
'/' => sub { ($_[2] or ( Scalar::Util::blessed ($_[1]) and $_[1]->isa (__PACKAGE__) ) )
? Carp::croak 'Illegal division by zero'
: 0
},
'<=>' => sub { $_[2]
? $_[1] <=> 0
: 0 <=> $_[1]
},
cmp => sub { $_[2]
? $_[1] cmp 0
: 0 cmp $_[1]
},
);
my $null;
sub AUTOLOAD {
$null = bless ( \ do{ 0 }, shift ) unless defined $null;
return $null;
}
sub import {
my $class = shift;
my $caller = caller(0);
no strict 'refs';
no warnings qw/uninitialized/;
while (@_) {
my $arg = shift;
if ($arg eq 'is_defined') {
*{"$caller\::is_defined"} = sub ($) {
if (defined $_[0] and not ( Scalar::Util::blessed ($_[0]) and $_[0]->isa (__PACKAGE__) ) ) {
return 1;
}
esle {
return 0;
}
};
}
else {
Carp::croak (qq/"$arg" is not exported by the $class module/);
}
}
}
sub all { return () } # so for ($rs->all) will work correctly
sub DESTROY {}
1;
package DBIx::Class::Null::Pattern;
use warnings;
use strict;
use base qw/DBIx::Class/;
use DBIx::Class::Null qw/is_defined/;
sub _inflated_column {
if (defined $_[2]) {
return next::method (@_);
}
return DBIx::Class::Null->new;
}
sub find_or_new_related {
my $self = shift;
my $obj = $self->find_related(@_);
return is_defined $obj ? $obj : $self->new_related(@_);
}
sub find_or_create_related {
my $self = shift;
my $obj = $self->find_related(@_);
return is_defined $obj ? $obj : $self->create_related(@_);
}
__PACKAGE__->load_components (qw/Core/);
__PACKAGE__->table ('bogus');
__PACKAGE__->resultset_class ('DBIx::Class::Resultset::Null::Pattern');
1;
package DBIx::Class::Resultset::Null::Pattern;
use warnings;
use strict;
use base qw/DBIx::Class::ResultSet/;
use DBIx::Class::Null qw/is_defined/;
use Data::Dumper;
use Devel::StackTrace;
sub single {
my $obj = shift->next::method (@_);
return is_defined $obj ? $obj : DBIx::Class::Null->new;
}
sub first {
my $obj = shift->next::method (@_);
return is_defined $obj ? $obj : DBIx::Class::Null->new;
}
sub find_or_new {
my $self = shift;
my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
my $hash = ref $_[0] eq 'HASH' ? shift : {@_};
my $exists = $self->find($hash, $attrs);
return is_defined $exists ? $exists : $self->new_result($hash);
}
sub find_or_create {
my $self = shift;
my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
my $hash = ref $_[0] eq 'HASH' ? shift : {@_};
my $exists = $self->find($hash, $attrs);
return is_defined $exists ? $exists : $self->create($hash);
}
1;
More information about the DBIx-Class
mailing list