FAQ
(I haven't used DBIx::Class and its ilk before so this might be a dumb
question)

I create a form. I submit with that form. I see the request go to the
test server with the data.

Now I want to take this data and stuff it into one of my model's tables.
I presume it is something like

__PACKAGE__->find_or_create({ key1 => $value1, key2 => $value2, ...} );


from the controller. This seems wrong to me though, in that wouldn't we
want to go through the model? I think I am missing something
fundamental here.

Is there a really dumb/simple example out there for perusal which
demonstrates taking data from a form and putting it into a database
using Catalyst? I can't seem to wrap my mind around the correct method,
as I don't see an example of it. I looked through the Agave site, and
it seems to be missing a few of the methods (addcomment is pretty much
what I want to see, but it doesn't appear to be in the tree).

Thanks.

Joe



--
Joseph Landman, Ph.D
Founder and CEO
Scalable Informatics LLC,
email: [email protected]
web : http://www.scalableinformatics.com
phone: +1 734 786 8423
fax : +1 734 786 8452
cell : +1 734 612 4615

Search Discussions

  • Andreas Marienborg at Dec 27, 2005 at 11:37 pm

    On 27. des. 2005, at 21.14, Joe Landman wrote:

    (I haven't used DBIx::Class and its ilk before so this might be a
    dumb question)

    I create a form. I submit with that form. I see the request go to
    the test server with the data.

    Now I want to take this data and stuff it into one of my model's
    tables. I presume it is something like

    __PACKAGE__->find_or_create({ key1 => $value1, key2 =>
    $value2, ...} );
    You usually have to replace __PACKAGE__ with the actual model-
    package, like MyApp::Model::Table->find_or_create

    In a controller, __PACKAGE__ equals the package of the controller,
    and that controller, most likely, lacks a find_or_create method.
    from the controller. This seems wrong to me though, in that
    wouldn't we want to go through the model? I think I am missing
    something fundamental here.

    Is there a really dumb/simple example out there for perusal which
    demonstrates taking data from a form and putting it into a database
    using Catalyst? I can't seem to wrap my mind around the correct
    method, as I don't see an example of it. I looked through the
    Agave site, and it seems to be missing a few of the methods
    (addcomment is pretty much what I want to see, but it doesn't
    appear to be in the tree).
    Check out the BookDB example from dev.catalyst.perl.org

    Thanks.

    Joe



    --
    Joseph Landman, Ph.D
    Founder and CEO
    Scalable Informatics LLC,
    email: [email protected]
    web : http://www.scalableinformatics.com
    phone: +1 734 786 8423
    fax : +1 734 786 8452
    cell : +1 734 612 4615


    _______________________________________________
    Catalyst mailing list
    [email protected]
    http://lists.rawmode.org/mailman/listinfo/catalyst
  • Joe Landman at Dec 28, 2005 at 7:39 am
    Ok, started playing with DBIx::Class and DBIx::Class::Table, and a toy
    database. Got a minimalistic test case going fine with that. Now to
    make it work with Catalyst.

    I did the "usual"

    catalyst.pl test
    cd test
    script/test_create.pl model Database DBIC dbi:SQLite:/root/test/db/test.db
    script/test_create.pl view Mason Mason

    I added the Mason component root setup and other bits. Then

    script/test_create.pl controller db

    The db has a single table named testing, with a very simple structure:


    CREATE TABLE testing (
    id INTEGER PRIMARY KEY,
    name text,
    size text
    );

    I added some simple data into it to make testing easier.

    sqlite> select * from testing;
    1|a|b
    2|c|d
    3|d|e

    In the test/Model/Database/Testing.pm package, I added a pointer to the
    table and added the columns

    __PACKAGE__->table('testing');
    __PACKAGE__->add_columns(qw/id name size/);

    I added a simple global list method to the db controller

    sub list : Global {
    use Data::Dumper;
    my ( $self, $c ) = @_;
    my (@all);
    @all = test::Model::Database::Testing->search();
    $c->forward( 'test::View::Mason');
    $c->stash->{stuff}=Dumper(@all);
    }

    Ok. Now I am getting an error message of

    [Wed Dec 28 04:06:40 2005] [catalyst] [error] Couldn't render component
    "/list" - error was "could not find component for initial path '/list'
    (component roots are: '/root/test/root/static')
    Stack:
    [/usr/lib/perl5/site_perl/5.8.6/HTML/Mason/Request.pm:204]

    for the http://dualcore:3000/list url.

    I think this is a Mason error and not a Catalyst error. I see the data
    in the stash at the end of the web page, and it is identical to what I
    generated with my DBIx::Class::Table bit. I think I know how to fix it,
    but I am not completely sure. Will experiment a bit more.

    My question is, apart from a Mason error, is this the right general
    path? Or I am doing something very wrong somewhere? Basically we are
    taking a Mason based application, and migrating it into Catalyst with a
    Mason view so we can do a saner job of extending/maintaining it. Our
    old method of DB interaction was rather different, so I am trying to get
    on a fast (re)learning curve :).

    Thanks again for the pointers and your patience.

    BTW: addcomment was not missing, I just didn't find it before posting.
    I did find it later. It was helpful as well.

    Joe

    Andreas Marienborg wrote:
    On 27. des. 2005, at 21.14, Joe Landman wrote:

    (I haven't used DBIx::Class and its ilk before so this might be a
    dumb question)

    I create a form. I submit with that form. I see the request go to
    the test server with the data.

    Now I want to take this data and stuff it into one of my model's
    tables. I presume it is something like

    __PACKAGE__->find_or_create({ key1 => $value1, key2 => $value2,
    ...} );
    You usually have to replace __PACKAGE__ with the actual model- package,
    like MyApp::Model::Table->find_or_create

    In a controller, __PACKAGE__ equals the package of the controller, and
    that controller, most likely, lacks a find_or_create method.
    from the controller. This seems wrong to me though, in that wouldn't
    we want to go through the model? I think I am missing something
    fundamental here.

    Is there a really dumb/simple example out there for perusal which
    demonstrates taking data from a form and putting it into a database
    using Catalyst? I can't seem to wrap my mind around the correct
    method, as I don't see an example of it. I looked through the Agave
    site, and it seems to be missing a few of the methods (addcomment is
    pretty much what I want to see, but it doesn't appear to be in the
    tree).
    Check out the BookDB example from dev.catalyst.perl.org

    Thanks.

    Joe



    --
    Joseph Landman, Ph.D
    Founder and CEO
    Scalable Informatics LLC,
    email: [email protected]
    web : http://www.scalableinformatics.com
    phone: +1 734 786 8423
    fax : +1 734 786 8452
    cell : +1 734 612 4615


    _______________________________________________
    Catalyst mailing list
    [email protected]
    http://lists.rawmode.org/mailman/listinfo/catalyst

    _______________________________________________
    Catalyst mailing list
    [email protected]
    http://lists.rawmode.org/mailman/listinfo/catalyst
    --
    Joseph Landman, Ph.D
    Founder and CEO
    Scalable Informatics LLC,
    email: [email protected]
    web : http://www.scalableinformatics.com
    phone: +1 734 786 8423
    fax : +1 734 786 8452
    cell : +1 734 612 4615
  • Joe Landman at Dec 28, 2005 at 7:45 am

    Joe Landman wrote:

    Ok. Now I am getting an error message of

    [Wed Dec 28 04:06:40 2005] [catalyst] [error] Couldn't render
    component "/list" - error was "could not find component for initial path
    '/list' (component roots are: '/root/test/root/static')
    Stack:
    [/usr/lib/perl5/site_perl/5.8.6/HTML/Mason/Request.pm:204]
    Yup... adding a template and a component name list seems to help... Ok,
    now we are cooking with fire ... :)

    Joe


    --
    Joseph Landman, Ph.D
    Founder and CEO
    Scalable Informatics LLC,
    email: [email protected]
    web : http://www.scalableinformatics.com
    phone: +1 734 786 8423
    fax : +1 734 786 8452
    cell : +1 734 612 4615
  • Andreas Marienborg at Dec 28, 2005 at 9:43 am
    I saw your other post, but figured I would comment some bits :)

    On 28. des. 2005, at 07.46, Joe Landman wrote:

    I added a simple global list method to the db controller

    sub list : Global {
    use Data::Dumper;
    my ( $self, $c ) = @_;
    my (@all);
    @all = test::Model::Database::Testing->search();
    $c->forward( 'test::View::Mason');
    put this in the 'sub end : Private { } of your base application, so
    you dont have to do it for each controller you write :P This also
    ensures that everything you put in the stash is visible upon rendering.

    You can also check out the DefaultEnd plugin, which is a grand idea :)
    $c->stash->{stuff}=Dumper(@all);
    }
  • Joe Landman at Dec 28, 2005 at 7:00 pm
    Following Andreas' advice, the dump of the all now displays!

    What I did is add (to the main application module)

    sub end : Private {
    my ( $self, $c ) = @_;
    $c->forward('test::View::Mason');
    }

    Good. Now modify the list method in the test::Controller::db.pm

    sub list : Local {
    use Data::Dumper;
    my ( $self, $c ) = @_;
    my (@all);
    @all = test::Model::Database::Testing->search();
    $c->stash->{stuff}=Dumper(@all);
    push @{$c->stash->{data}},@all;
    $c->stash->{template}="test.html";
    $c->forward( 'test::View::Mason');
    }

    so that $c->stash->{data} has the stuff I want to display in the view,
    and then modify the view so that it does something with the incoming
    data ...

    <%args>
    $stuff => undef
    $data => undef
    </%args>
    % use Data::Dumper;
    % my ($k,$string,$dump,$maxid);
    % $dump = Dumper($data);
    % $maxid=-10;
    in Test.html: Dumping....<br />
    <hr />
    <pre>
    <% $stuff %>
    </pre>
    <hr />
    <!-- Dump of data = <% $dump %> -->
    <pre>
    % foreach (@{$data})
    % {
    % $string = undef;
    % if ($maxid < $_->{_column_data}->{id}) { $maxid $_->{_column_data}->{id}; }
    % foreach $k (keys %{$_->{_column_data}})
    % {
    % $string .= sprintf "| %s ",$_->{_column_data}->{$k};
    % }
    <% $string %>
    % }
    </pre>

    and we get (ignoring the dump)
    a | 1 | b
    c | 2 | d
    d | 3 | e
    which is exactly what I wanted.

    Great!

    So to mix it up, now I want to add a tiny form at the end of this to add
    another row to the database. So I appended

    <form action="add" method="post">
    Name: <input type="text" name="name" value="" size@ /> <br />
    Size: <input type="text" name="size" value="" size@ /> <br />
    ID: <input type="text" name="id" value="<% $maxid+1 %>" size@ />
    <br />
    <input type="submit" value="submit">
    </form>

    to the test.html, and created an add method in test::Controller::db.pm

    sub add : Local {
    my ( $self, $c ) = @_;
    my (@all,%all2);
    %all2 =$c->parameters;
    $c->stash->{stuff}=Dumper(\%all2);
    $c->stash->{template}="test.html";
    $c->forward( 'test::View::Mason');
    }

    The idea is that $c->{parameters} is a hash of the incoming posted
    parameters.

    Unfortunately, it seems to get lost somewhere. I see it in the debug
    messages on the console


    [Wed Dec 28 15:29:37 2005] [catalyst] [debug]
    **********************************
    [Wed Dec 28 15:29:37 2005] [catalyst] [debug] * Request 1 (0.250/s) [26826]
    [Wed Dec 28 15:29:37 2005] [catalyst] [debug]
    **********************************
    [Wed Dec 28 15:29:37 2005] [catalyst] [debug] Body Parameters are:
    .---------------------------------------+--------------------------------------.
    Key | Value
    +---------------------------------------+--------------------------------------+
    id | 4

    name | asdasdasd

    size | asdasdasda
    '---------------------------------------+--------------------------------------'

    [Wed Dec 28 15:29:37 2005] [catalyst] [debug] "POST" request for
    "db/add" from "192.168.1.32"
    [Wed Dec 28 15:29:37 2005] [catalyst] [debug] Path is "db/add"
    [Wed Dec 28 15:29:37 2005] [catalyst] [debug] Rendering component
    "/test.html"
    [Wed Dec 28 15:29:37 2005] [catalyst] [debug] Rendering component
    "/test.html"
    [Wed Dec 28 15:29:37 2005] [catalyst] [info] Request took 0.018545s
    (53.923/s)
    .------------------------------------------------------------------+-----------.
    Action |
    Time |
    +------------------------------------------------------------------+-----------+
    -> test::View::Mason->process |
    0.002368s |
    /db/add |
    0.002898s |
    -> test::View::Mason->process |
    0.000978s |
    /end |
    0.001180s |
    '------------------------------------------------------------------+-----------'


    but it does not show up in the method call. Is there some magic I need
    to do here? I will look back over the Agave and other examples.
    Somewhat confused here. Is there any way to force the debug screen even
    on successful calls?

    Joe


    Andreas Marienborg wrote:
    I saw your other post, but figured I would comment some bits :)

    On 28. des. 2005, at 07.46, Joe Landman wrote:

    I added a simple global list method to the db controller

    sub list : Global {
    use Data::Dumper;
    my ( $self, $c ) = @_;
    my (@all);
    @all = test::Model::Database::Testing->search();
    $c->forward( 'test::View::Mason');
    put this in the 'sub end : Private { } of your base application, so you
    dont have to do it for each controller you write :P This also ensures
    that everything you put in the stash is visible upon rendering.

    You can also check out the DefaultEnd plugin, which is a grand idea :)
    $c->stash->{stuff}=Dumper(@all);
    }
    --
    Joseph Landman, Ph.D
    Founder and CEO
    Scalable Informatics LLC,
    email: [email protected]
    web : http://www.scalableinformatics.com
    phone: +1 734 786 8423
    fax : +1 734 786 8452
    cell : +1 734 612 4615
  • Joe Landman at Dec 28, 2005 at 7:13 pm
    Allrighty... got it working ... I think I get it now.

    Would the Catalyst folks like a blow-by-blow writeup and howto for
    people who are not used to DBIx:Class and other methods?

    Might help newbies...


    Joe

    Joe Landman wrote:
    Following Andreas' advice, the dump of the all now displays!

    What I did is add (to the main application module)

    sub end : Private {
    my ( $self, $c ) = @_;
    $c->forward('test::View::Mason');
    }

    Good. Now modify the list method in the test::Controller::db.pm

    sub list : Local {
    use Data::Dumper;
    my ( $self, $c ) = @_;
    my (@all);
    @all = test::Model::Database::Testing->search();
    $c->stash->{stuff}=Dumper(@all);
    push @{$c->stash->{data}},@all;
    $c->stash->{template}="test.html";
    $c->forward( 'test::View::Mason');
    }

    so that $c->stash->{data} has the stuff I want to display in the view,
    and then modify the view so that it does something with the incoming
    data ...

    <%args>
    $stuff => undef
    $data => undef
    </%args>
    % use Data::Dumper;
    % my ($k,$string,$dump,$maxid);
    % $dump = Dumper($data);
    % $maxid=-10;
    in Test.html: Dumping....<br />
    <hr />
    <pre>
    <% $stuff %>
    </pre>
    <hr />
    <!-- Dump of data = <% $dump %> -->
    <pre>
    % foreach (@{$data})
    % {
    % $string = undef;
    % if ($maxid < $_->{_column_data}->{id}) { $maxid > $_->{_column_data}->{id}; }
    % foreach $k (keys %{$_->{_column_data}})
    % {
    % $string .= sprintf "| %s ",$_->{_column_data}->{$k};
    % }
    <% $string %>
    % }
    </pre>

    and we get (ignoring the dump)
    a | 1 | b
    c | 2 | d
    d | 3 | e
    which is exactly what I wanted.

    Great!

    So to mix it up, now I want to add a tiny form at the end of this to add
    another row to the database. So I appended

    <form action="add" method="post">
    Name: <input type="text" name="name" value="" size@ /> <br />
    Size: <input type="text" name="size" value="" size@ /> <br />
    ID: <input type="text" name="id" value="<% $maxid+1 %>" size@
    /> <br />
    <input type="submit" value="submit">
    </form>

    to the test.html, and created an add method in test::Controller::db.pm

    sub add : Local {
    my ( $self, $c ) = @_;
    my (@all,%all2);
    %all2 =$c->parameters;
    $c->stash->{stuff}=Dumper(\%all2);
    $c->stash->{template}="test.html";
    $c->forward( 'test::View::Mason');
    }

    The idea is that $c->{parameters} is a hash of the incoming posted
    parameters.

    Unfortunately, it seems to get lost somewhere. I see it in the debug
    messages on the console


    [Wed Dec 28 15:29:37 2005] [catalyst] [debug]
    **********************************
    [Wed Dec 28 15:29:37 2005] [catalyst] [debug] * Request 1 (0.250/s)
    [26826]
    [Wed Dec 28 15:29:37 2005] [catalyst] [debug]
    **********************************
    [Wed Dec 28 15:29:37 2005] [catalyst] [debug] Body Parameters are:
    .---------------------------------------+--------------------------------------.
    Key | Value |
    +---------------------------------------+--------------------------------------+
    id | 4 |
    name | asdasdasd |
    size | asdasdasda |
    '---------------------------------------+--------------------------------------'


    [Wed Dec 28 15:29:37 2005] [catalyst] [debug] "POST" request for
    "db/add" from "192.168.1.32"
    [Wed Dec 28 15:29:37 2005] [catalyst] [debug] Path is "db/add"
    [Wed Dec 28 15:29:37 2005] [catalyst] [debug] Rendering component
    "/test.html"
    [Wed Dec 28 15:29:37 2005] [catalyst] [debug] Rendering component
    "/test.html"
    [Wed Dec 28 15:29:37 2005] [catalyst] [info] Request took 0.018545s
    (53.923/s)
    .------------------------------------------------------------------+-----------.
    Action |
    Time |
    +------------------------------------------------------------------+-----------+
    -> test::View::Mason->process |
    0.002368s |
    /db/add |
    0.002898s |
    -> test::View::Mason->process |
    0.000978s |
    /end |
    0.001180s |
    '------------------------------------------------------------------+-----------'



    but it does not show up in the method call. Is there some magic I need
    to do here? I will look back over the Agave and other examples.
    Somewhat confused here. Is there any way to force the debug screen even
    on successful calls?

    Joe


    Andreas Marienborg wrote:
    I saw your other post, but figured I would comment some bits :)

    On 28. des. 2005, at 07.46, Joe Landman wrote:

    I added a simple global list method to the db controller

    sub list : Global {
    use Data::Dumper;
    my ( $self, $c ) = @_;
    my (@all);
    @all = test::Model::Database::Testing->search();
    $c->forward( 'test::View::Mason');
    put this in the 'sub end : Private { } of your base application, so
    you dont have to do it for each controller you write :P This also
    ensures that everything you put in the stash is visible upon rendering.

    You can also check out the DefaultEnd plugin, which is a grand idea :)
    $c->stash->{stuff}=Dumper(@all);
    }
    --
    Joseph Landman, Ph.D
    Founder and CEO
    Scalable Informatics LLC,
    email: [email protected]
    web : http://www.scalableinformatics.com
    phone: +1 734 786 8423
    fax : +1 734 786 8452
    cell : +1 734 612 4615
  • Matt S Trout at Dec 28, 2005 at 7:50 pm

    On Tue, Dec 27, 2005 at 11:43:43PM +0100, Andreas Marienborg wrote:
    Now I want to take this data and stuff it into one of my model's
    tables. I presume it is something like

    __PACKAGE__->find_or_create({ key1 => $value1, key2 =>
    $value2, ...} );
    You usually have to replace __PACKAGE__ with the actual model-
    package, like MyApp::Model::Table->find_or_create
    Aieee, don't do that!

    $c->model('Table') is better because that way you can move that controller
    code into another app without having to trudge through a search-and-replace.

    --
    Matt S Trout Offering custom development, consultancy and support
    Technical Director contracts for Catalyst, DBIx::Class and BAST. Contact
    Shadowcat Systems Ltd. mst (at) shadowcatsystems.co.uk for more information

    + Help us build a better perl ORM: http://dbix-class.shadowcatsystems.co.uk/ +
  • Joe Landman at Dec 28, 2005 at 8:55 pm
    test::Model::Database::Testing->find_or_create works

    $c->model('Testing')->find_or_create fails (Caught exception "Can't
    call method "find_or_create" on an undefined value at
    /root/test/script/../lib/test/Controller/db.pm line 24.")

    $c->model('Database::Testing)->find_or_create works.

    Hmmm... must have built the model wrong. This is what I used

    script/test_create.pl model Database DBIC dbi:SQLite:/root/test/db/test.db

    Should that be

    script/test_create.pl model DBIC dbi:SQLite:/root/test/db/test.db

    ??

    Joe

    Matt S Trout wrote:
    On Tue, Dec 27, 2005 at 11:43:43PM +0100, Andreas Marienborg wrote:
    Now I want to take this data and stuff it into one of my model's
    tables. I presume it is something like

    __PACKAGE__->find_or_create({ key1 => $value1, key2 =>
    $value2, ...} );
    You usually have to replace __PACKAGE__ with the actual model-
    package, like MyApp::Model::Table->find_or_create
    Aieee, don't do that!

    $c->model('Table') is better because that way you can move that controller
    code into another app without having to trudge through a search-and-replace.
    --
    Joseph Landman, Ph.D
    Founder and CEO
    Scalable Informatics LLC,
    email: [email protected]
    web : http://www.scalableinformatics.com
    phone: +1 734 786 8423
    fax : +1 734 786 8452
    cell : +1 734 612 4615
  • Matt S Trout at Dec 28, 2005 at 9:23 pm

    On Wed, Dec 28, 2005 at 03:02:21PM -0500, Joe Landman wrote:
    test::Model::Database::Testing->find_or_create works

    $c->model('Testing')->find_or_create fails (Caught exception "Can't
    call method "find_or_create" on an undefined value at
    /root/test/script/../lib/test/Controller/db.pm line 24.")

    $c->model('Database::Testing)->find_or_create works.
    Correct.

    I used a single name ('Table') because I was replying to a post that used
    MyApp::Model::Table. Your model's fine.

    Please don't assume what I type into an e-mail can be copied and pasted and
    will Just Work - I usually type straight into the e-mail to illustrate a
    point so it may not even be syntactically correct if I wasn't paying
    attention :)

    --
    Matt S Trout Offering custom development, consultancy and support
    Technical Director contracts for Catalyst, DBIx::Class and BAST. Contact
    Shadowcat Systems Ltd. mst (at) shadowcatsystems.co.uk for more information

    + Help us build a better perl ORM: http://dbix-class.shadowcatsystems.co.uk/ +

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupcatalyst @
categoriescatalyst, perl
postedDec 27, '05 at 9:08p
activeDec 28, '05 at 9:23p
posts10
users3
websitecatalystframework.org
irc#catalyst

People

Translate

site design / logo © 2023 Grokbase