[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