[Dbix-class] Fun with auto-restricted result sets
David Ihnen
davidi at norchemlab.com
Wed Feb 18 19:13:42 GMT 2009
So in the wake of fREW showing a modification of the classes to allow
the modification of the delete, I utilized a corrollary concept...
restricting a result set automatically/transparently, as you would in
case of that delete - not normally showing the deleted rows. In my
case, my alerts table has a possible action window, possibly has been
dismissed, and possibly might be inactive. This made the resultset
class more complicated, but not unmanageable. It was fun to work through
the logic of modifying an arbitrarily complex requested search clause.
If you specify values for these, it is assumed you know what you're
doing and this result set class won't further modify the terms. I may
have missed the handling of already defined alert_expire terms though...
maybe I should make it inactive if you specify any of the terms anywhere
in the \%where tree.
package DB::Schema::active_alert_resultset;
use base 'DBIx::Class::ResultSet';
sub search {
my $self = shift;
$_[0]->{'inactive'} ||= 0;
$_[0]->{'dismissed'} ||= \"IS NULL";
$_[0]->{'alert_time'} ||= { '<' => \"NOW()" };
my $aeor = [];
push @{$aeor}, { alert_expire => { '>' => \'NOW()'} };
push @{$aeor}, { alert_expire => \'IS NULL' };
if ($_[0]->{'-or'}) { # If there is already an -or, we need to nest
it into an -and
# so we don't overwrite the term, or change
the logic by orring with it.
my $and = $_[0]->{'-and'} ||= []; # Use an existing -and term if
already supplied.
push @{$and}, { -or => delete $_[0]->{'-or'} }; # Move the old -and
push @{$and}, { -or => $aeor }; # add our alert expire or term
} else {
$_[0]->{'-or'} = $aeor;
}
return $self->next::method( @_ );
}
The utilization of the table is a bit more tangled... I had to change
the way I defined my table. Since normal access is through the
restricted set, I renamed the unrestricted set to alerts_all and kept
alerts for my restricted set. The source-define-inline recipe was
snarfed from a coworker who snarfed it from somewhere else. I added the
resultset_class directive for my custom resultset class.
>>>>>OLD
package DB::Schema::alerts;
use base qw/DB::Schema/;
use strict;
__PACKAGE__->load_components(qw/PK::Auto InflateColumn::DateTime Core/);
__PACKAGE__->table('alerts');
>>>>NEW
package DB::Schema::alerts_all; # change class name to alerts_all!
use base qw/DB::Schema/;
use strict;
__PACKAGE__->load_components(qw/PK::Auto InflateColumn::DateTime Core/);
__PACKAGE__->table('alerts');
__PACKAGE__->source_name('alerts_all'); # manually set source name to
be diff than table!
<...other column and rel definition stuff here..>
my $source = __PACKAGE__->result_source_instance();
my $alerts = $source->new($source);
@DB::Schema::alerts::ISA = ('DB::Schema::alerts_all');
$alerts->result_class('DB::Schema::alerts');
$alerts->source_name('alerts');
$alerts->resultset_class('DB::Schema::active_alert_resultset'); # my
new resultset class!
DB::Schema->register_source( 'alerts' => $alerts );
------
Now whenever you access result source alerts, you get the restricted
result set! Viola!
But how do you get the alerts_all?
->resultset('alerts_all') is fine
But if you use a rel, like has_many('alerts', "DB::Schema::alerts'...
You can define another rel that works for the all set
But if you use a rel, like has_many('alerts_all',
"DB::Schema::alerts_all'...
So far, it works. Isn't engineering fun?
David
More information about the DBIx-Class
mailing list