>
> David Ihnen wrote:
>>>
>>>> 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( @_ );
>>>> }
>>>>
>>>
>>> You're only checking to see if the given columns have specified values
>>> passed in, but what if ->search was called on a resultset object that
>>> *already* has constraints for these columns?
>>>
>> What?  How can you be in a result class and not in it too?  Can you give
>> an example of how to write that in code?
>>
>>
>>  Until DBIC goes Moose, it's tricky (and not very safe) to introspect an
>>> existing RS to see what's already been done to it...
>>>
>> If I have already restricted the resultset, then re-restricting it by the
>> same terms will filter out whats not there, right?  And asking for dismissed
>> => \'IS NOT NULL' on an alerts (or derived) resultset will always give you
>> empty set.  No active alerts have dismissed NOT NULL
>>
>
> The problem comes when you try to "derive" one resultset from another; any
> criteria not present are clobbered by your default assumptions. Let's say
> that one part of your code retrieves inactive alerts:
>
>  my $rs = $schema->resultset('alert')->search({inactive => 1});
>
> Then another part of your code wants to take that same result set and limit
> it to just those alerts from last year:
>
>  my $new_rs = $rs->search({alert_time => {'<' => \'current_yr()'}});
>  # replacing 'current_yr()' with the appropriate syntax for your dbms
>
> Using your methodology, this invocation of ->search will set 'inactive'
> back to '0', because it's not passed in.
>
> Of course, if you only call search once with both criteria, you don't have
> a problem. But I've been finding the additive technique (sometimes referred
> to as "resultset chaining") to make for very clean, readable, maintainable
> code. In fact, you could use such an approach as an alternative to
> overriding ->search with your defaults:
>
>  package DB::ResultSet::alerts;
>  use base 'DBIx::Class::ResultSet';
>
>  sub active {
>      return shift->search({
>          inactive   => 0,
>          dismissed  => \'is null',
>          alert_time => { '<' => \"NOW()" }
>          '-or' => [
>              { alert_expire => { '>' => \'NOW()'} },
>              { alert_expire => \'IS NULL' },
>          ],
>      });
>  }
>
> Then anywhere in your code that you want to enforce "activeness", just do:
>
>  my $rs = $schema->resultset('alerts')->active->search({foo => 'bar'});
>
> It's not *quite* as slick as having it defaulted automatically, but it
> protects you from unwittingly clobbering previously set criteria.


>From IRC conversations it appears that really the slickest way to do these
things is to define a ResultSource (not result set) as that can help you
with joins and whatnot as well.  I plan on using this for my Paranoid
Deletion setup, but I can't *just* work on the DB side at work, so it will
have to wait a bit :-)
-- 
fREW Schmidt
http://blog.afoolishmanifesto.com
_______________________________________________
List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
IRC: irc.perl.org#dbix-class
SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
Searchable Archive: http://www.grokbase.com/group/[email protected]

Reply via email to