>
> 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]