FAQ
Hi.

Im working on a new app which is working well. While doing it though i realised that i never get my serach done right. I mean, it works, but
i end up spending a lot of code munging parameters, making adjustments,
and so forth, and this cant be right. What should be a few lines takes a page or two of code, just for a simple one or two table search.

I tried looking through the docs for a best-practices approach and unless i missed something there arent ANY examples of search in the docs, the tutorial, the wiki, the Advent.... (Oh in one place there was something about harder searches, fulltext in PostGres, but nothing general.)

Is there any place that shows a simple example of a web form -> DBIC search in Catalyst? And if not, shouldnt there be?

Thanks!

Jen

Search Discussions

  • Peter Karman at Sep 23, 2008 at 8:53 pm

    Dr. Jennifer Nussbaum wrote on 09/23/2008 02:38 PM:

    Is there any place that shows a simple example of a web form -> DBIC
    search in Catalyst? And if not, shouldnt there be?
    The problem is that db search quickly becomes complicated when you're
    dealing with multiple tables, relationships, column types, etc.

    See Search::QueryParser::SQL on CPAN for my attempt at this. There is a
    dbic() method too.

    CatalystX::CRUD::Model::Utils depends on S::QP::S to turn
    $c->req->params into a query, if you want to look at one example.
  • Zbigniew Lukasiak at Sep 23, 2008 at 9:02 pm

    On Tue, Sep 23, 2008 at 9:38 PM, Dr. Jennifer Nussbaum wrote:
    Hi.

    Im working on a new app which is working well. While doing it though i realised that i never get my serach done right. I mean, it works, but
    i end up spending a lot of code munging parameters, making adjustments,
    and so forth, and this cant be right. What should be a few lines takes a page or two of code, just for a simple one or two table search.

    I tried looking through the docs for a best-practices approach and unless i missed something there arent ANY examples of search in the docs, the tutorial, the wiki, the Advent.... (Oh in one place there was something about harder searches, fulltext in PostGres, but nothing general.)

    Is there any place that shows a simple example of a web form -> DBIC search in Catalyst? And if not, shouldnt there be?
    Hi there,

    I am sure you are referring to
    http://www.catalystframework.org/calendar/2007/16 :) I don't really
    know what you need, but I start that article with a very a simple
    solution:

    my @records = $schema->ResultSet( 'MyTable' )->search(
    $reqest->params,
    { page => 1, rows => 5 }
    );

    Only after presenting that I start discussing what to do when you need
    to add some more complex predicates to the query and propose a
    solution to that.

    Of course that article ignores the part of generating the HTML form
    code and getting the parameters from $c - I had to concentrate on
    somethign.
  • Dr. Jennifer Nussbaum at Sep 23, 2008 at 9:21 pm

    --- On Tue, 9/23/08, Zbigniew Lukasiak wrote:

    From: Zbigniew Lukasiak <[email protected]>
    Subject: Re: [Catalyst] Search example in any docs?
    To: [email protected], "The elegant MVC web framework" <[email protected]>
    Date: Tuesday, September 23, 2008, 1:02 PM
    On Tue, Sep 23, 2008 at 9:38 PM, Dr. Jennifer Nussbaum
    wrote:
    Hi.

    Im working on a new app which is working well. While
    doing it though i realised that i never get my serach done
    right. I mean, it works, but
    i end up spending a lot of code munging parameters,
    making adjustments,
    and so forth, and this cant be right. What should be a
    few lines takes a page or two of code, just for a simple one
    or two table search.
    I tried looking through the docs for a best-practices
    approach and unless i missed something there arent ANY
    examples of search in the docs, the tutorial, the wiki, the
    Advent.... (Oh in one place there was something about harder
    searches, fulltext in PostGres, but nothing general.)
    Is there any place that shows a simple example of a
    web form -> DBIC search in Catalyst? And if not, shouldnt
    there be?

    Hi there,

    I am sure you are referring to
    http://www.catalystframework.org/calendar/2007/16 :) I
    don't really
    know what you need, but I start that article with a very a
    simple
    solution:

    my @records = $schema->ResultSet( 'MyTable'
    )->search(
    $reqest->params,
    { page => 1, rows => 5 }
    );

    Only after presenting that I start discussing what to do
    when you need
    to add some more complex predicates to the query and
    propose a
    solution to that.
    Yes i did see that and i did try it, but i quickly found that i ran into all sorts of problems. For example my params would usually include something
    like a "action" param with the value "Submit query", whihc doesnt work so well when it hits the database ;-)

    Thanks to Peter Karman for his other suggestion, which i will look at in more detail. I guess i do stuff like that by hand all the time--i have
    code that looks like

    if ( $c->req->params->{title} ) {
    my $title = "%" . $c->req->params->{title} . "%";
    push (@$query, { title => { like => $title } });
    }

    # exact match here
    if ( $c->req->params->{author} ) {
    my $performer = $c->req->params->{author};
    push (@$query, { author => { '=' => $author} });
    }

    etc., which just looks messy.

    In any case i do think this should be at least MENTIONED in some of the docs. The fact that it gets complicated doesnt mean it should be ignored,
    surely everyone has to do this in Cat.

    Thanks!

    Jen
  • Tomas Doran at Sep 23, 2008 at 11:41 pm

    On 23 Sep 2008, at 21:21, Dr. Jennifer Nussbaum wrote:
    i have
    code that looks like

    if ( $c->req->params->{title} ) {
    my $title = "%" . $c->req->params->{title} . "%";
    push (@$query, { title => { like => $title } });
    }

    # exact match here
    if ( $c->req->params->{author} ) {
    my $performer = $c->req->params->{author};
    push (@$query, { author => { '=' => $author} });
    }

    etc., which just looks messy.
    It's called refactoring - pull the common bits out and put them in a
    base class for your controllers.

    package MyApp::Controller;
    use strict;

    sub query_like {
    my ($self, $c, $name) = @_;
    return $self->query($c, $name, 'like', '%' . $c->req->param
    ($name) . '%');
    }

    sub query_eq {
    my ($self, $c, $name) = @_;
    return $self->query($c, $name, '=', $c->req->param($name));
    }

    sub _query {
    my ($self, $c, $name, $operator, $val) = @_;
    if ($c->req->param($name)) {
    push @{$c->stash->{query}}, { $name => { $operator => $val } };
    }
    };

    package MyApp::Controller::Search;

    sub foo : Local {
    my ($self, $c) = @_;
    $self->query_like($c, 'title');
    $self->query_eq($c, 'author');
    }

    Cheers
    t0m
  • Dr. Jennifer Nussbaum at Sep 24, 2008 at 12:34 am

    --- On Tue, 9/23/08, Tomas Doran wrote:

    From: Tomas Doran <[email protected]>
    Subject: Re: [Catalyst] Search example in any docs?
    To: [email protected], "The elegant MVC web framework" <[email protected]>
    Date: Tuesday, September 23, 2008, 3:41 PM
    On 23 Sep 2008, at 21:21, Dr. Jennifer Nussbaum wrote:
    i have
    code that looks like

    if ( $c->req->params->{title} ) {
    my $title = "%" .
    $c->req->params->{title} . "%";
    push (@$query, { title => { like => $title } });
    }

    # exact match here
    if ( $c->req->params->{author} ) {
    my $performer =
    $c->req->params->{author};
    push (@$query, { author => { '=' =>
    $author} });
    }

    etc., which just looks messy.
    It's called refactoring - pull the common bits out and
    put them in a
    base class for your controllers.
    Thanks. I do appreciate this, and its a neat solution, but the problem wasnt that i dont know how to put common elements in a base class, the
    problem is that nowhere in the Cat docs, formal or informal, are there any examples of doing searches with web apps.

    In practice i tend to have more complicated apps, with difficult queries, that i do abstract out the query building, and then things that i
    throw together in a few minutes where everythings a mess. Usually when im just throwing things together, i forget about best practices and want
    to look them up.

    Jen
  • Jay Shirley at Sep 24, 2008 at 1:45 am

    On Tue, Sep 23, 2008 at 4:34 PM, Dr. Jennifer Nussbaum wrote:

    --- On Tue, 9/23/08, Tomas Doran wrote:
    From: Tomas Doran <[email protected]>
    Subject: Re: [Catalyst] Search example in any docs?
    To: [email protected], "The elegant MVC web framework" <[email protected]>
    Date: Tuesday, September 23, 2008, 3:41 PM
    On 23 Sep 2008, at 21:21, Dr. Jennifer Nussbaum wrote:
    i have
    code that looks like

    if ( $c->req->params->{title} ) {
    my $title = "%" .
    $c->req->params->{title} . "%";
    push (@$query, { title => { like => $title } });
    }

    # exact match here
    if ( $c->req->params->{author} ) {
    my $performer =
    $c->req->params->{author};
    push (@$query, { author => { '=' =>
    $author} });
    }

    etc., which just looks messy.
    It's called refactoring - pull the common bits out and
    put them in a
    base class for your controllers.
    Thanks. I do appreciate this, and its a neat solution, but the problem wasnt that i dont know how to put common elements in a base class, the
    problem is that nowhere in the Cat docs, formal or informal, are there any examples of doing searches with web apps.
    Right, because any solution would be model specific. Which puts it in
    the realm of wiki nodes or CatalystX modules that profess preference
    for an ORM model.
    In practice i tend to have more complicated apps, with difficult queries, that i do abstract out the query building, and then things that i
    throw together in a few minutes where everythings a mess. Usually when im just throwing things together, i forget about best practices and want
    to look them up.

    Jen
    Wiki! Wiki! Document what you've done and post on here. Wiki nodes
    are a living document and can evolve with time and evolve into better
    solutions.

    What you're asking for is more a model, though, not Catalyst (which is
    just a framework, no more, no less).

    -J
  • Jesse Sheidlower at Sep 24, 2008 at 3:00 pm

    On Tue, Sep 23, 2008 at 05:45:17PM -0700, J. Shirley wrote:
    On Tue, Sep 23, 2008 at 4:34 PM, Dr. Jennifer Nussbaum
    wrote:

    Thanks. I do appreciate this, and its a neat solution, but the problem wasnt that i dont know how to put common elements in a base class, the
    problem is that nowhere in the Cat docs, formal or informal, are there any examples of doing searches with web apps.
    Right, because any solution would be model specific. Which puts it in
    the realm of wiki nodes or CatalystX modules that profess preference
    for an ORM model. [...]
    Wiki! Wiki! Document what you've done and post on here. Wiki nodes
    are a living document and can evolve with time and evolve into better
    solutions.

    What you're asking for is more a model, though, not Catalyst (which is
    just a framework, no more, no less).
    I'm about to get on a plane now, but I did want to comment on this
    thread, as someone at least theoretically concerned with the docs.

    Though there have now been several responses along
    J. Shirley's lines, I have to say that I agree with the OP
    here. It doesn't matter if a search-generation routine is tied
    to one or another ORM, it should be documented somewhere, as
    this is a very common task. The docs are very heavily tied to
    specific elements--most of them assume you're using DBIC; the
    Tutorial shows the use of DBIC and FormFu; everything shows TT
    views, etc. If you're using the Rose modules for your DB
    layer, there's a lot less in the docs; if you're using DFV for
    forms (as I do) there's not much there; etc. So there's no
    reason that search can't also be demonstrated using DBIC.

    So I don't think that showing a basic search example using
    DBIC would somehow violate the idea of Catalyst-as-framework.
    I hope the OP does document her ideas on the wiki, and it would
    be nice if Zbigniew does exend the Advent article. But a short
    addition to the Tutorial showing a simple search, or a Cookbook
    entry on this, would, I think, be a Good Thing.

    Jesse Sheidlower
  • Jay Shirley at Sep 24, 2008 at 3:53 pm

    On Wed, Sep 24, 2008 at 7:00 AM, Jesse Sheidlower wrote:
    On Tue, Sep 23, 2008 at 05:45:17PM -0700, J. Shirley wrote:
    On Tue, Sep 23, 2008 at 4:34 PM, Dr. Jennifer Nussbaum
    wrote:

    Thanks. I do appreciate this, and its a neat solution, but the problem wasnt that i dont know how to put common elements in a base class, the
    problem is that nowhere in the Cat docs, formal or informal, are there any examples of doing searches with web apps.
    Right, because any solution would be model specific. Which puts it in
    the realm of wiki nodes or CatalystX modules that profess preference
    for an ORM model. [...]
    Wiki! Wiki! Document what you've done and post on here. Wiki nodes
    are a living document and can evolve with time and evolve into better
    solutions.

    What you're asking for is more a model, though, not Catalyst (which is
    just a framework, no more, no less).
    I'm about to get on a plane now, but I did want to comment on this
    thread, as someone at least theoretically concerned with the docs.

    Though there have now been several responses along
    J. Shirley's lines, I have to say that I agree with the OP
    here. It doesn't matter if a search-generation routine is tied
    to one or another ORM, it should be documented somewhere, as
    this is a very common task. The docs are very heavily tied to
    specific elements--most of them assume you're using DBIC; the
    Tutorial shows the use of DBIC and FormFu; everything shows TT
    views, etc. If you're using the Rose modules for your DB
    layer, there's a lot less in the docs; if you're using DFV for
    forms (as I do) there's not much there; etc. So there's no
    reason that search can't also be demonstrated using DBIC.
    The tutorial is the only one that assumes DBIC. That isn't
    necessarily the technical documentation of Catalyst. That is a
    Catalyst Tutorial.

    I view docs as what is under the Catalyst::Manual space, though. If
    you count wiki and advent calendars, sure, but the problem has been
    posted about on the advent calendars. I suggested the wiki, though.

    I do think that TT is the standard view in the docs, mostly because it
    has the least offensive syntax to people just wanted to read what is
    going on. DBIC (or any model class) is not that way. You have to
    learn DBIC for it to really make sense.
    So I don't think that showing a basic search example using
    DBIC would somehow violate the idea of Catalyst-as-framework.
    I hope the OP does document her ideas on the wiki, and it would
    be nice if Zbigniew does exend the Advent article. But a short
    addition to the Tutorial showing a simple search, or a Cookbook
    entry on this, would, I think, be a Good Thing.
    CatalystX::Cookbook would probably be the better place for it, rather
    than in Catalyst::Manual. Bonus points for included code (perhaps in
    the form of t/search.t and t/lib/TestApp/Controller/Search.pm?)

    -J
  • Kenny Gatdula at Sep 24, 2008 at 6:46 pm

    On Sep 23, 2008, at 8:45 PM, J. Shirley wrote:
    Wiki! Wiki! Document what you've done and post on here. Wiki nodes
    are a living document and can evolve with time and evolve into better
    solutions.
    Because I love little diversions like this, here you go. http://dev.catalystframework.org/wiki/wikicookbook/searchexample

    Kenny
  • Jay Shirley at Sep 24, 2008 at 11:38 pm

    On Wed, Sep 24, 2008 at 10:46 AM, Kenny Gatdula wrote:
    On Sep 23, 2008, at 8:45 PM, J. Shirley wrote:

    Wiki! Wiki! Document what you've done and post on here. Wiki nodes
    are a living document and can evolve with time and evolve into better
    solutions.
    Because I love little diversions like this, here you go.
    http://dev.catalystframework.org/wiki/wikicookbook/searchexample

    Kenny
    Everybody owes Kenny a beer for starting it, and then please add in
    your own recipes and comments (or add your comments, then buy him a
    beer)

    Although linking to localhost:3000 may not DWYM :)
  • Tomas Doran at Sep 24, 2008 at 9:31 am

    On 24 Sep 2008, at 00:34, Dr. Jennifer Nussbaum wrote:
    Thanks. I do appreciate this, and its a neat solution, but the
    problem wasnt that i dont know how to put common elements in a base
    class, the
    problem is that nowhere in the Cat docs, formal or informal, are
    there any examples of doing searches with web apps.
    You're making the assumption here that Catalyst and DBIx::Class are
    the same thing. I'm not actually a DBIx::Class user myself, and there
    are plenty of people who aren't using it..
    In practice i tend to have more complicated apps, with difficult
    queries, that i do abstract out the query building, and then things
    that i
    throw together in a few minutes where everythings a mess. Usually
    when im just throwing things together, i forget about best
    practices and want
    to look them up.
    However, here you have a good point.

    One of the main strengths of Catalyst is that it's so easy to combine
    it with whatever set of other technologies you're using - but that
    doesn't mean that the documentation or community currently does the
    right thing by newer users who are confused by the level/number of
    choices open to them.. Also, having made a choice - there is little
    documentation about the common / recommended patterns and practices
    for combining various components in a non-trivial manor.

    It would be fantastic if there were more higher level documentation
    about the available components, and when/why you would want to employ
    them, combined with a lot more in-depth documentation about patterns
    and practices for combining Catalyst with a particular model /
    component to form a non-trivial application, accompanied by annotated
    demo applications showing the features/patterns in use.

    A lot of this knowledge is already buried in Catalyst applications
    (for example MojoMojo and Angerwhale both make pretty good reading,
    and if you're feeling like you need your brain stretched, Reaction
    will certainly do that) - however developing and maintaining
    comprehensive documentation / annotated commentary is non-trivial in
    itself, keeping it in pace with the applications themselves is
    probably a non-starter. Extracting enough of the complexity to show
    the patterns to good use into a demo application (and then
    maintaining said application) is also nontrivial undertaking. This
    isn't any criticism to the Catalyst documentation team - I think that
    the docs we do have are great, and well maintained in line with
    Catalyst itself.

    Another key problem is that it's also extremely hard for people who
    are familiar with the code bases in question to write good
    documentation - you can only do that as you're learning.

    My recommendation to anyone trying Catalyst for the first time, or
    trying a new piece of software with Catalyst / trying to find
    patterns or examples of prior art would be that once you've been
    through the available documentation on CPAN and the wiki, had a play,
    and formed your problem domain in your head, is to pop by irc -
    #catalyst is one of the most helpful channels I've ever been in, and
    whilst the inhabitants can be brusque, I see people wander by and
    take great advice away daily. (Note, as you're using DBIx::Class,
    they're likely to send you to #dbic). People there will also have no
    problem with deconstructing the specific problem you're trying to
    solve back to your problem domain, finding the higher level problem,
    and then telling you that you're solving it in a non-optimum way (and
    the approach they recommend for solving it).

    If everyone who came into irc and was helped were to spend the same
    time people had donated to helping them in writing up the help /
    knowledge they'd just received on the wiki, then all the things which
    I dismissed as 'nontrivial' above, would suddenly become possible.
    Some dream eh?

    Cheers
    t0m

    P.S. Come ask about what you want in #catalyst / #dbic and get it
    written up on the catalyst wiki, plzkthnx?
  • Zbigniew Lukasiak at Sep 24, 2008 at 10:26 am

    On Tue, Sep 23, 2008 at 10:21 PM, Dr. Jennifer Nussbaum wrote:

    --- On Tue, 9/23/08, Zbigniew Lukasiak wrote:
    Hi there,

    I am sure you are referring to
    http://www.catalystframework.org/calendar/2007/16 :) I
    don't really
    know what you need, but I start that article with a very a
    simple
    solution:

    my @records = $schema->ResultSet( 'MyTable'
    )->search(
    $reqest->params,
    { page => 1, rows => 5 }
    );

    Only after presenting that I start discussing what to do
    when you need
    to add some more complex predicates to the query and
    propose a
    solution to that.
    Yes i did see that and i did try it, but i quickly found that i ran into all sorts of problems. For example my params would usually include something
    like a "action" param with the value "Submit query", whihc doesnt work so well when it hits the database ;-)
    Perhaps something like: $params = $c->req->params; delete $params->{action}; ?

    You further talk about the 'LIKE' queries etc. It must be my writing
    skills or maybe I did a too big step between the simple solution and
    the complex ones - but answering the question on how to extend the
    basic search in a clean way was exactly the point of my article. If
    you ask this question then I must have failed in my goal - so excuse
    my persistance but I would like to persue it a bit further.

    So here is a simple search with a 'LIKE' operator on mycolumn.

    sub search_for_mycolumn {
    my ( $self, $params ) = @_;
    my %search_params = { mycolumn => { 'like' => '%' .
    $params->{my_column} . '%' };
    $self = $self->search( \%search_params );
    return $self;
    }

    The key is that advanced_search will look for methods called
    search_for_* and use them automatically for the search. You can
    combine it with the exact matches (that you don't need to write any
    additional method for) and any other complex predicates. The full
    advantage of this technique might not be visible for simple cases like
    this one - but I am sure that as soon as you add tags into that you'll
    find it cleaner.

    Now I think I should have written a full example - so that the reader
    would see how the parts need to be assembled.

    So your ResultSet class would be something like:

    use base AdvancedSearch;

    sub search_for_mycolumn {
    my ( $self, $params ) = @_;
    my %search_params = { mycolumn => { 'like' => '%' .
    $params->{my_column} . '%' };
    $self = $self->search( \%search_params );
    return $self;
    }
    ... (other complex searches here) ...
    1;

    And the code in your controller would be similar to:

    my $params = $c->req->params;
    delete $params->{action};
    my $result_set = $c->model( 'MyModel')->ResultSet( 'MyTable' );
    my @records = $result_set->advanced_search(
    $params,
    { page => 1, rows => 5 }
    );


    Maybe an update would fit for the next Advent Calendar?

    Cheers,
    Zbigniew

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupcatalyst @
categoriescatalyst, perl
postedSep 23, '08 at 8:38p
activeSep 24, '08 at 11:38p
posts13
users7
websitecatalystframework.org
irc#catalyst

People

Translate

site design / logo © 2023 Grokbase