[Catalyst] YA CRUD module

David Schmidt davewood at gmx.at
Sun Dec 4 16:24:25 GMT 2011


davewood: I have a problem with CatalystX::Component::Traits. When i
apply 2 traits and one requires some methods provided by the other an
error appears saying ... "Couldn't instantiate component ... requires
the methods ..."

Caelum: davewood: you can't do that, the traits are applied all at once



Guess I'll try to inject a controller and add the traits then. like
CatalystX::SimpleLogin does it.




On 4 December 2011 14:37, David Schmidt <davewood at gmx.at> wrote:
> Hi t0m
>
> I am currently stuck at configuring/applying roles via TestApp::config
>
> I want to apply the role via catalyst config in MyApp.pm
>
> __PACKAGE__->config(
>   'Controller::Resource' => {
>      resultset_key => 'cds_rs',
>      resources_key => 'cds',
>      resource_key => 'cd',
>      model => 'DB::CDs',
>      traits => ['
>         '+CatalystX::Controller::TraitFor::Resource',
>         '+CatalystX::Controller::TraitFor::Role::List',
>      ],
>   },
> );
>
> Using 'CatalystX::Component::Traits'; I get a test to run when I only
> apply the Resource trait. But once I add the List role the following
> error appears.
>
> $ prove -l t/04_with_role.t
> t/04_with_role.t .. Couldn't instantiate component
> "TestApp::Controller::Root",
> "'CatalystX::TraitFor::Controller::Resource|CatalystX::TraitFor::Controller::Role::List'
> requires the methods 'resources_key' and 'resultset_key' to be
> implemented by 'Moose::Meta::Class::__ANON__::SERIAL::11' at
> /usr/local/lib/perl/5.10.1/Moose/Meta/Role/Application.pm line 53
>        Moose::Meta::Role::Application::apply('Moose::Meta::Role::Application::ToClass=HASH(0xa3732a0)',
> 'Moose::Meta::Class::__ANON__::SERIAL::12=HASH(0xa3684e8)',
> 'Moose::Meta::Class::__ANON__::SERIAL::5=HASH(0xa355838)') called at
> /usr/local/lib/perl/5.10.1/Moose/Meta/Role/Application/ToClass.pm line
> 33
>        Moose::Meta::Role::Application::ToClass::apply('Moose::Meta::Role::Application::ToClass=HASH(0xa3732a0)',
> 'Moose::Meta::Class::__ANON__::SERIAL::12=HASH(0xa3684e8)',
> 'Moose::Meta::Class::__ANON__::SERIAL::5=HASH(0xa355838)',
> 'HASH(0xa3813e8)') called at
> /usr/local/lib/perl/5.10.1/Moose/Meta/Role.pm line 482
>        Moose::Meta::Role::apply('Moose::Meta::Class::__ANON__::SERIAL::12=HASH(0xa3684e8)',
> 'Moose::Meta::Class::__ANON__::SERIAL::5=HASH(0xa355838)') called at
> /usr/local/share/perl/5.10.1/MooseX/MethodAttributes/Role/Meta/Role/Application.pm
> line 26
>        Class::MOP::Class:::around('CODE(0x9966858)',
> 'Moose::Meta::Class::__ANON__::SERIAL::12=HASH(0xa3684e8)',
> 'Moose::Meta::Class::__ANON__::SERIAL::5=HASH(0xa355838)') called at
> /usr/local/lib/perl/5.10.1/Class/MOP/Method/Wrapped.pm line 161
>        Class::MOP::Method::Wrapped::__ANON__('Moose::Meta::Class::__ANON__::SERIAL::12=HASH(0xa3684e8)',
> 'Moose::Meta::Class::__ANON__::SERIAL::5=HASH(0xa355838)') called at
> /usr/local/lib/perl/5.10.1/Class/MOP/Method/Wrapped.pm line 91
>        Moose::Meta::Class::__ANON__::SERIAL::12::apply('Moose::Meta::Class::__ANON__::SERIAL::12=HASH(0xa3684e8)',
> 'Moose::Meta::Class::__ANON__::SERIAL::5=HASH(0xa355838)') called at
> /usr/local/lib/perl/5.10.1/Moose/Util.pm line 157
>        Moose::Util::_apply_all_roles('Moose::Meta::Class::__ANON__::SERIAL::5=HASH(0xa355838)',
> undef, 'CatalystX::TraitFor::Controller::Resource',
> 'CatalystX::TraitFor::Controller::Role::List') called at
> /usr/local/lib/perl/5.10.1/Moose/Util.pm line 93
>        Moose::Util::apply_all_roles('Moose::Meta::Class::__ANON__::SERIAL::5=HASH(0xa355838)',
> 'CatalystX::TraitFor::Controller::Resource',
> 'CatalystX::TraitFor::Controller::Role::List') called at
> /usr/local/lib/perl/5.10.1/Moose/Meta/Class.pm line 98
>        Moose::Meta::Class::create('Moose::Meta::Class::__ANON__::SERIAL::5=HASH(0xa2f59a0)',
> 'Moose::Meta::Class::__ANON__::SERIAL::11', 'roles',
> 'ARRAY(0xa33d798)', 'weaken', '', 'superclasses', 'ARRAY(0x9ba6ac8)')
> called at /usr/local/lib/perl/5.10.1/Class/MOP/Package.pm line 121
>        Class::MOP::Package::create_anon('Moose::Meta::Class::__ANON__::SERIAL::5=HASH(0xa2f59a0)',
> 'superclasses', 'ARRAY(0x9ba6ac8)', 'roles', 'ARRAY(0xa33d798)',
> 'cache', 1) called at /usr/local/lib/perl/5.10.1/Class/MOP/Class.pm
> line 473
>        Class::MOP::Class::create_anon_class('Moose::Meta::Class::__ANON__::SERIAL::5=HASH(0xa2f59a0)',
> 'superclasses', 'ARRAY(0x9ba6ac8)', 'roles', 'ARRAY(0xa33d798)',
> 'cache', 1) called at
> /usr/local/share/perl/5.10.1/MooseX/Traits/Pluggable.pm line 120
>        MooseX::Traits::Pluggable::_build_instance_with_traits('TestApp::Controller::Root',
> 'TestApp::Controller::Root', 'TestApp') called at
> /usr/local/share/perl/5.10.1/MooseX/Traits/Pluggable.pm line 97
>        MooseX::Traits::Pluggable::new_with_traits('TestApp::Controller::Root',
> 'TestApp', 'HASH(0xa301858)') called at
> /usr/local/share/perl/5.10.1/CatalystX/Component/Traits.pm line 145
>        CatalystX::Component::Traits::COMPONENT('TestApp::Controller::Root',
> 'TestApp', 'HASH(0xa1306b8)') called at
> /usr/local/share/perl/5.10.1/Catalyst.pm line 2525
>        eval {...} called at /usr/local/share/perl/5.10.1/Catalyst.pm line 2525
>        Catalyst::setup_component('TestApp',
> 'TestApp::Controller::Root') called at
> /usr/local/share/perl/5.10.1/Catalyst.pm line 2452
>        Catalyst::setup_components('TestApp') called at
> /usr/local/share/perl/5.10.1/Catalyst.pm line 1179
>        Catalyst::setup('TestApp') called at
> /home/david/CatalystX-TraitFor-Controller-Resource/t/lib/TestApp.pm
> line 24
>        require TestApp.pm called at t/04_with_role.t line 9
>        main::BEGIN() called at
> /home/david/CatalystX-TraitFor-Controller-Resource/t/lib/TestApp.pm
> line 0
>        eval {...} called at
> /home/david/CatalystX-TraitFor-Controller-Resource/t/lib/TestApp.pm
> line 0"Compilation failed in require at t/04_with_role.t line 9.
> BEGIN failed--compilation aborted at t/04_with_role.t line 9.
> # Looks like your test exited with 9 before it could output anything.
> t/04_with_role.t .. Dubious, test returned 9 (wstat 2304, 0x900)
> Failed 3/3 subtests
>
> Test Summary Report
> -------------------
> t/04_with_role.t (Wstat: 2304 Tests: 0 Failed: 0)
>  Non-zero exit status: 9
>  Parse errors: Bad plan.  You planned 3 tests but ran 0.
> Files=1, Tests=0,  1 wallclock secs ( 0.00 usr  0.06 sys +  0.37 cusr
> 0.68 csys =  1.11 CPU)
> Result: FAIL
>
>
> # t/04_with_role.t
>  1 use strict;
>  2 use warnings;
>  3
>  4 use FindBin;
>  5 use lib "$FindBin::Bin/lib";
>  6
>  7 use Test::More tests => 3;
>  8
>  9 use TestApp;
>  10
>  11 my $testapp = TestApp->new();
>  12
>  13 my $controller = $testapp->controller('Root');
>  14 isa_ok ( $controller, 'TestApp::Controller::Root' );
>  15
>  16 my $action;
>  17 $action = $controller->action_for('base');
>  18 ok ( defined($action), 'Action "base" exists.' );
>  19
>  20 my $action = $controller->action_for('list');
>  21 ok ( defined($action), 'Action "list" exists.' );
>
> # TestApp.pm
>  1 package TestApp;
>  2
>  3 use strict;
>  4 use warnings;
>  5 use Catalyst;
>  6
>  7 use Moose;
>  8 use namespace::autoclean;
>  9
>  10 __PACKAGE__->config(
>  11     name => 'TestApp',
>  12     'Controller::Root' => {
>  13         resultset_key   => 'cds_rs',
>  14         resources_key   => 'cds',
>  15         resource_key    => 'cd',
>  16         model           => 'DB::CDs',
>  17         traits => [
>  18             '+CatalystX::TraitFor::Controller::Resource,
>  19             '+CatalystX::TraitFor::Controller::Role::List'',
>  20         ],
>  21     }
>  22 );
>  23
>  24 __PACKAGE__->setup();
>  25
>  26 1;
>
>
>  1 package TestApp::Controller::Root;
>  2
>  3 use Moose;
>  4 BEGIN { extends 'Catalyst::Controller'; }
>  5 with 'CatalystX::Component::Traits';
>  6
>  7 __PACKAGE__->config->{namespace} = '';
>  8
>  9 sub index : Path Args(0) {
>  10     my ($self, $c) = @_;
>  11     $c->res->body('index');
>  12 }
>  13
>  14 1;
>
>
> On 31 October 2011 22:08, Tomas Doran <bobtfish at bobtfish.net> wrote:
>>
>> On 31 Oct 2011, at 14:49, David Schmidt wrote:
>>
>>> It's about time I publish my first CPAN module and it happens to be
>>> yet another CRUD module.
>>>
>>> Feedback greatly appreciated.
>>
>>
>>
>> I haven't looked at this in depth - but it generally looks nice (other than
>> lack of tests).. But some comments:
>>
>> You don't need strict or warnings. MX::MethodAttributes::Role gives you all
>> the same stuff Moose::Role does, which includes strict and warnings.
>>
>> It might be nice if you could split the roles up..
>>
>> So there would be a (very base) role, and then separate
>> List/Show/Edit/Create/Delete roles, and the main role would just compose
>> everything...
>>
>> But that would allow you to more easily / naturally only use a subset of the
>> functionality, whilst implementing some of the code in a more custom manor..
>> Of course you can do this by adding around method modifiers to methods -
>> however having several classes with half a dozen modifiers each which
>> redirect to a 404 (to remove edit / delete functionality) is a lot less nice
>> than only composing a subset of the roles (if for no other reason than that
>> the wrapped things will show up in the debug table)..
>>
>> The documentation on parent_key doesn't quite seem to make sense, and the
>> predicate naming there is also not clear.. (It may make sense why it isn't
>> called what you expect - but could do with a comment?)
>>
>> form_class could be made a MooseX::Types::LoadableClass to avoid the
>> explicit class load.
>>
>> I intensely dislike your sub _redirect - couldn't you instead compute a
>> private path, and pass that to $c->uri_for_action to produce a 'proper' URI?
>>
>> This would enable people to use your resources at sub-path parts, as you
>> could pass the captures in.
>>
>> e.g.
>>
>> /user/<id>
>> /user/<id>/.... resources from your role
>> /user/<id>/document/<id>
>> /user/<id>/document/<id>/.... resources from your role
>>
>> In the latter case, you could / would chain off the base_with_id action for
>> the user id... This is the part where it becomes 'fun', and where your
>> 'parent' functionality comes in - I guess these two things could be nicely
>> combined... :)
>>
>> Is it sensible to give it an 'index' action? I'd be tempted to rename this
>> to 'list', so that if someone wanted to override the default index, they
>> could just override the PathPart of the 'list' action, and provide their own
>> index action..
>>
>> Your delete works with GET requests. This is a horribly bad idea as it makes
>> GETs stop being idempotent... Same deal with edit/create I guess...
>>
>> I look forward to seeing a TestApp - this code looks like a great start on
>> something really interesting :)
>>
>> Cheers
>> t0m
>>
>>
>>
>>
>> _______________________________________________
>> List: Catalyst at lists.scsys.co.uk
>> Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
>> Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
>> Dev site: http://dev.catalyst.perl.org/



More information about the Catalyst mailing list