[Catalyst] Dispatch matching more than the path?

Garrett Goebel ggoebel at goebel.ws
Thu Sep 7 05:06:35 CEST 2006


On Sep 6, 2006, at 3:35 PM, John Napiorkowski wrote:

> Garrett,
>
> Looks like we are working on something similar.  I
> hadn't noticed your postings about two weeks about (I
> was in the middle of moving from Beijing back to the
> USA and missed about a week of Catalyst postings) or I
> might have saved time asking the same questions you
> asked.
>
> I'm actually doing this as an Action class.  Since I
> don't find any additional posts I'm not sure your
> status.  Want to collaborate?  I am also very
> interested in REST based services and would enjoy
> having someone to bounce ideas off of.
>
>

I've just been through something similar. Moving back to the USA from  
Lima, Peru.

I spent the week following that last post dissecting InstantCRUD and  
rewriting something similar but RESTful for the work I've previously  
mentioned. I had to present something that kinda sorta worked on the  
28th. Which led to many shortcuts being taken. I'm still not happy  
with where I'm at. But the last week of transitioning back to the  
states and getting the kids into school is settling down. Reminder to  
self... I still need to send a foreign key patch for  
DBIx::Class::Schema::Loader::DBI::SQLite to Brandon.

I'd be happy to collaborate. I'm fully aware that I'm unaware of  
Catalyst best practices. And like you, I'd love to bounce ideas and  
code around.

Perhaps you could start by describing your goals and your approach in  
more detail. I still need to convert my hacked Catalyst::Action into  
an class derived from ActionClass. If I get some time tomorrow, I'll  
work that up and post some code.

cheers,

Garrett


> --- Garrett Goebel <ggoebel at goebel.ws> wrote:
>
>> On Aug 22, 2006, at 3:49 AM, Matt S Trout wrote:
>>>> Garrett Goebel wrote:
>>>>
>>>> I hacked something into the Path and Regex
>> dispatchers to get
>> collective
>>>> matching on method and path working in the
>> prototype.
>>>
>>> You shouldn't need to hack anything into these;
>> just use a custom
>> ActionClass
>>> that overrides $action->match to introspect onto
>> the request
>> method and
>>> anything else you need (this is already how :Args
>> is handled, see the
>>> Catalyst::Action source for the implementation).
>>
>> Thanks. I'd found the :Args code in Catalyst::Action
>> last night and
>> managed to shoehorn the request method and path
>> parameter matching
>> checks into it. How to subclass or override it was
>> going to be my
>> next question. I'll check out using a custom
>> ActionClass.
>>
>> Last night I also sub-classed the Request class to
>> add:
>> __PACKAGE__->mk_accessors(qw/path_parameters
>> accept_extension/);
>>
>> And I'm currently subclassing the Dispatcher to
>> override
>> prepare_action in order to:
>> o  remove uri path parameters from $c->request->path
>> and add to
>>     $c->request->path_parameters
>> o  remove "file" extension from last path segment
>> and add to
>>     $c->request->accept_extension
>> o  filter body parameters from using content_type
>> implied by the
>>     accept_extension (json, yaml, etc) and add to
>> $c->request-
>>> parameters.
>>     Perhaps I should consider just using the
>> $c->request->content_type?
>> o  check POST requests for hidden _method=DELETE|PUT
>> parameter and
>> update
>>     $c->request->method accordingly
>>
>> These are all things I want to do once per request,
>> not once per
>> action. Certainly there are better places to perform
>> some of these
>> tasks. And I would like to hear any advice on the
>> best place to
>> override catalyst for each. In the mean time, at
>> least I've got a
>> proof of concept working.
>>
>>
>> My controller now is able to look like:
>>
>> # GET http://foo.com/model
>> # GET http://foo.com/model.json
>> sub index :GET :Path('') Args(0) {
>>      my ($self, $c) = @_;
>>      my @models = grep {
>> UNIVERSAL::can($c->model($_),
>> 'result_source') }
>>                   $c->models;
>>      $self->out($c, \@models);
>>      1;
>> }
>>
>> # GET http://foo.com/model/Person
>> sub show :GET :Path('') :Args(1) {
>>      my ($self, $c, $model) = @_;
>>      my @pkcols =
>> $c->model($model)->result_source->primary_columns;
>>      my @pk_tuples = map(
>>          { my $tuple = $_; csv_encode(map({
>> $tuple->$_ } @pkcols)) }
>>          $c->model($model)->search(undef,
>>                                    {columns  =>
>> \@pkcols,
>>                                     distinct => 1,
>>                                     order_by =>
>> \@pkcols})
>>      );
>>      $self->out($c, \@pk_tuples);
>>      1;
>> }
>>
>> # GET http://foo.com/model/Person;edit
>> sub edit :GET :Path('') :PathParam(edit) :Args(1)
>> {...}
>>
>> # GET http://foo.com/model/Person;add
>> sub add :GET :Path('') :PathParam(add) :Args(1)
>> {...}
>>
>>
>> # GET http://foo.com/model/Person;column_info
>> # GET http://foo.com/model/Person.yaml;column_info
>> sub show_column_info :GET :Path('')
>> :PathParam(column_info) :Args(1) {
>>      my ($self, $c, $model) = @_;
>>      my $rs  = $c->model($model)->result_source;
>>      my %column_info = map { $_ =>
>> $rs->column_info($_)} $rs->columns;
>>      $self->out($c, \%column_info);
>>      1;
>> }
>>
>> # POST http://foo.com/model/Person;new
>> sub create :POST :Path('') :PathParam(new) :Args(1)
>> {...}
>>
>> # PUT http://foo.com/model/Person/32
>> sub update :PUT :Path('') :Args(2) {...}
>>
>> # DELETE http://foo.com/model/Person/32
>> sub destroy :DELETE :Path('') :Args(2) {...}
>>




More information about the Catalyst mailing list