[Catalyst] Sanity Check -- requesting feedback on chaining approach

Eden Cardim edencardim at gmail.com
Wed Feb 16 04:28:21 GMT 2011


>>>>> "will" == will trillich <will.trillich at serensoft.com> writes:

    will> Catalystas -- this chaining stuff is wicked awesome. We've
    will> been following the below paradigm for the most part, and now
    will> we want to expand a bit: package MyApp::Controller::Xyzzy;

    will> sub base     : Chained         PathPart('xyzzy') CaptureArgs(0) {  }
    will>   sub list   : Chained('base') PathPart('')             Args(0) {  }
    will>   sub item   : Chained('base') PathPart('')      CaptureArgs(1) {  }
    will>     sub view : Chained('item') PathPart('')             Args(0) {  }

    will> The two new nodes we want to insert are for csv-download
    will> (delivering all records) and paging (delivering a
    will> subset). Here's what we're thinking:

    will> package MyApp::Controller::Xyzzy;
    will> sub base     : Chained         PathPart('xyzzy') CaptureArgs(0) {  }
    will>   sub list   : Chained('base') PathPart('')      CaptureArgs(0) {  }
    will>     sub page : Chained('list') PathPart('')             Args(0) {  }
    will>     sub csv  : Chained('list') PathPart('csv')          Args(0) {  }
    will>   sub item   : Chained('base') PathPart('')      CaptureArgs(1) {  }
    will>     sub view : Chained('item') PathPart('')             Args(0) {  }

    will> Here the index view would come from page() instead of directly
    will> from list(). csv() would download
    will> resultset->search->({%params})->all whereas page() would
    will> resultset-> search({%params},{page=>$p,rows=>$r}).

    will> So any search parameters would be handled inside list() and
    will> then paging parameters would be handled separately inside
    will> page(). Right? Is there an elegant way to separate the two
    will> sets of parameters?

Yes, this will work:

# in list()
$c->stash->{rs} =
  $c->model('Foo')->search({%params});

# in page()
$c->stash->{paged_rs} =
  $c->stash->{rs}->search({}, {page => $p, rows => $r});

...if that's what you're asking.

Other interesting things you can do:

sub add_item :Chained('list') PathPart('add') Args(0) {
    my($self, $c) = @_;
    $c->stash->{rs}->create({ %more_params })
}

sub related_items :Chained('list') PathPart('related') CaptureArgs(0) {
    my($self, $c) = @_;
    $c->stash->{rs} = $c->stash->{rs}->related_resultset('');
}

sub related_page :Chained('related_items') PathPart('page') Args(0) {
    my($self, $c) = @_;
    $c->forward('page');
}

sub related_csv :Chained('related_items') PathPart('csv') Args(0) {
    my($self, $c) = @_;
    $c->forward('csv');
}

Assuming %params in list() was a simple key/value map, add_items() is
going to use those, in addition to whatever's in %more_params, which is
cool because if you change the criteria in list(), it propagates
everywhere else as well. Plus, you reuse the page/csv implementation
easily. The combination of chained DBIC resultsets and catalyst chains
is very similar to curried functions (I believe that's what the initial
design goal was).

-- 
Eden Cardim
Software Engineer
Shadowcat Systems Ltd.
http://www.shadowcat.co.uk
http://blog.edencardim.com



More information about the Catalyst mailing list