[Dbix-class] best practices for sub-grouping results?

Jason Gottshall jgottshall at capwiz.com
Mon Mar 31 20:50:29 BST 2008


Given the typical CD/Artist example schema:

Artist->has_many(cds)
Genre->has_many(cds)
CD->belongs_to(artist)
CD->belongs_to(genre)
CD->add_column(release_year)

I have a CD search page, where the user may wish to group (categorize)
the results under sub-headings by artist, genre, or release year. It
seems I should be able to use a single template for this, given a data
structure (or object?) over which it can iterate in two nested loops;
outer loop for selected category, inner loop for results in that
category. But what should that data structure/object look like?

If I start with a CD resultset, based on the search criteria, I can
easily get a new rs for the category headings if their based on a
relationship:

$cd_rs = $schema->resultset('CD')->search(...);
$categorizer = 'artist'; # or $c->req->param('grouped_by');
$cat_rs = $cd_rs->search_related($categorizer);

But as I loop over that rs, how do I enuerate just the members of the
category?

[% WHILE (cat = cat_rs.next %]
  <h2>[% cat.name %]</h2>
  <ul>
  [% FOREACH cd IN cat.cds %]
    <li>[% cd.title %]</li>
  [% END %]
[% END %]

That will list every CD in each category, not just the ones that matched
the original search criteria. And I don't want to have to resort to:

  [% FOREACH cd IN cd_rs.search{{ "me.${categorizer}_id" => cat.id }) %]

That's too much exposure of the model API in the template, plus it seems
inefficient. And of course, this technique won't work at all if the user
wants to group by a column that isn't a foreign key, like release_year.
There's no way to get an rs for the categories to begin with.

Has anyone else found an elegant/efficient solution to this problem?
I've been toying with the idea of creating some sort of DBIC::RSGrouped
component to encapsulate this scenario, but I don't want to trudge too
far down that road without some advice from the community!

--Jason
jgottshall at capwiz.com



More information about the DBIx-Class mailing list