Login | Register For Free | Help
Search for: (Advanced)

Mailing List Archive: Catalyst: Users

Overriding chained methods.

 

 

Catalyst users RSS feed   Index | Next | Previous | View Threaded


moseley at hank

Feb 15, 2012, 4:40 PM

Post #1 of 4 (220 views)
Permalink
Overriding chained methods.

I have an app that is naturally hierarchical, so to make up an example a
path might be:

/version1/country/12/region/31/state/12/city/45


which I use Chained actions to implement. And the Controllers follow that
layout as well:

App/Controller/Version1/Country/Region/State/City.pm


Here's where I need some ideas:

Say at some point I need to change the API for an action in the City.pm
controller in a non-compatible way. I woud like to be able to just
override that ONE method in a new controller. For example, by adding this
(note the version number change)

App/Controller/Version2/Country/Region/State/City.pm


which contains just the method I want to override, and then "inherit" from
the version 1. Of course, ALL actions in version 1 would be available in
version 2.

I've have done something similar in the past, but without using Chained
actions -- although in that case the need was for a set of /guest/ actions
that had a subset of the app's actions, and I just had the /guest/*
controllers inherit from the original controllers.

Any suggestions?


--
Bill Moseley
moseley [at] hank


moseley at hank

Feb 15, 2012, 5:26 PM

Post #2 of 4 (225 views)
Permalink
Re: Overriding chained methods. [In reply to]

On Thu, Feb 16, 2012 at 7:40 AM, Bill Moseley <moseley [at] hank> wrote:

> I have an app that is naturally hierarchical, so to make up an example a
> path might be:
>
> /version1/country/12/region/31/state/12/city/45
>
>
> which I use Chained actions to implement.
>

BTW -- On a side note (and as a sanity check) here's how I'm implementing
this. It's a REST style app, and I need actions:

GET /country/123/region -- "list" all regions in the country
POST /country/123/region - add to the "list" of regions in that country.

GET /country/123/region/456 - get the specific "item"
PUT, DELETE as normal.

I'm always working with a "list" or an "item" in each controller -- so
decided to just standardize on that and write less code.

Then my controllers mostly look like this:

package App::Controller::Country::Region;
use Moose;
use namespace::autoclean;
BEGIN { extends 'Catalyst::Controller::REST' }
with 'App::ChainedREST';


sub list_GET {} # /country/$id/region

sub item_GET {} # /country/$id/region/$id

before args => sub { ... ] # or whatever.

And so on.

My poorly-named "ChainedREST' role looks mostly like this:

sub base : Chained( '../arg' ) CaptureArgs(0) { }
sub list : Chained( 'base' ) PathPart( '' ) : Args(0) ActionClass(REST) { }

sub arg : Chained( 'base' ) PathPart( '') CaptureArgs(1) {}
sub item : Chained( 'arg' ) PathPart( '' ) : Args(0) ActionClass(REST) { }




Means I must add an "args" action to my Root controller. And I also have a
BUILDARGS method to set the PathPart based on the
controller's name:

before BUILDARGS => sub {
my $class = shift;
my ( $name ) = $class =~ /::([^:]+)$/;

$class->config->{action}{base}{PathPart} ||= lc $name;

return;
};




--
Bill Moseley
moseley [at] hank


moseley at hank

Feb 18, 2012, 6:18 PM

Post #3 of 4 (201 views)
Permalink
Re: Overriding chained methods. [In reply to]

On Thu, Feb 16, 2012 at 7:40 AM, Bill Moseley <moseley [at] hank> wrote:

> Any suggestions?
>

Perhaps not. And rightly so.

What I was asking it how to override potentially any method in a chain of
Actions and to magically swap the the root of the chain. Sounds ugly and
confusing.

Perhaps a more sane approach is to capture the version number and for very
small API changes just return data conditionally on the version number, and
for anything more significant branch the app and run two versions at the
same time and deprecate the old version.

Or better, don't break backwards capability, and provide a version in the
response headers.



On Thu, Feb 16, 2012 at 7:40 AM, Bill Moseley <moseley [at] hank> wrote:

> I have an app that is naturally hierarchical, so to make up an example a
> path might be:
>
> /version1/country/12/region/31/state/12/city/45
>
>
> which I use Chained actions to implement. And the Controllers follow that
> layout as well:
>
> App/Controller/Version1/Country/Region/State/City.pm
>
>
> Here's where I need some ideas:
>
> Say at some point I need to change the API for an action in the City.pm
> controller in a non-compatible way. I woud like to be able to just
> override that ONE method in a new controller. For example, by adding this
> (note the version number change)
>
> App/Controller/Version2/Country/Region/State/City.pm
>
>
> which contains just the method I want to override, and then "inherit" from
> the version 1. Of course, ALL actions in version 1 would be available in
> version 2.
>
> I've have done something similar in the past, but without using Chained
> actions -- although in that case the need was for a set of /guest/ actions
> that had a subset of the app's actions, and I just had the /guest/*
> controllers inherit from the original controllers.
>
> Any suggestions?
>
>
> --
> Bill Moseley
> moseley [at] hank
>



--
Bill Moseley
moseley [at] hank


edencardim at gmail

Feb 21, 2012, 5:42 AM

Post #4 of 4 (194 views)
Permalink
Re: Re: Overriding chained methods. [In reply to]

>>>>> "Bill" == Bill Moseley <moseley [at] hank> writes:

Bill> What I was asking it how to override potentially any method in a
Bill> chain of Actions and to magically swap the the root of the
Bill> chain.  Sounds ugly and confusing.

That's perfectly viable, here's a few scenarios:

- override the action sub and declare the new attributes accordingly
- if you don't want to mess with the chaining, make the chained
action forward to a private action, then override it
- if you do want to mess with the attributes (Chained, PathPart, etc.) use
configuration in the child controller, like this:

__PACKAGE__->config(action => { foo => { Chained => '/bar } });

Note that you can make any method in a controller magically become an action,
by merely providing config in the way described above.

--
Eden Cardim Need help with your Catalyst or DBIx::Class project?
Code Monkey http://www.shadowcat.co.uk/catalyst/
Shadowcat Systems Ltd. Want a managed development or deployment platform?
http://edencardim.com http://www.shadowcat.co.uk/servers/

_______________________________________________
List: Catalyst [at] lists
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst [at] lists/
Dev site: http://dev.catalyst.perl.org/

Catalyst users RSS feed   Index | Next | Previous | View Threaded
 
 


Interested in having your list archived? Contact Gossamer Threads
 
  Web Applications & Managed Hosting Powered by Gossamer Threads Inc.