X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=catagits%2FCatalyst-Controller-DBIC-API.git;a=blobdiff_plain;f=lib%2FCatalyst%2FController%2FDBIC%2FAPI.pm;h=2a72e280038738e473e598463c1ecafe5489af51;hp=b6ef5bc4c1da51e263229c1c78ee6c346ae9ad1d;hb=810de6afa72cd92df2a6749ef85af7cce31302e7;hpb=0f0f8776b6d8d9c311b7004d1d46db3026670cdf diff --git a/lib/Catalyst/Controller/DBIC/API.pm b/lib/Catalyst/Controller/DBIC/API.pm index b6ef5bc..2a72e28 100644 --- a/lib/Catalyst/Controller/DBIC/API.pm +++ b/lib/Catalyst/Controller/DBIC/API.pm @@ -15,9 +15,9 @@ use Try::Tiny; use Catalyst::Controller::DBIC::API::Request; use namespace::autoclean; -with 'Catalyst::Controller::DBIC::API::StoredResultSource'; -with 'Catalyst::Controller::DBIC::API::StaticArguments'; -with 'Catalyst::Controller::DBIC::API::RequestArguments' => { static => 1 }; +with 'Catalyst::Controller::DBIC::API::StoredResultSource', + 'Catalyst::Controller::DBIC::API::StaticArguments', + 'Catalyst::Controller::DBIC::API::RequestArguments' => { static => 1 }; __PACKAGE__->config(); @@ -29,24 +29,25 @@ __PACKAGE__->config(); __PACKAGE__->config ( action => { setup => { PathPart => 'artist', Chained => '/api/rpc/rpc_base' } }, # define parent chain action and partpath - class => 'MyAppDB::Artist', # DBIC schema class - create_requires => ['name', 'age'], # columns required to create - create_allows => ['nickname'], # additional non-required columns that create allows - update_allows => ['name', 'age', 'nickname'], # columns that update allows - update_allows => ['name', 'age', 'nickname'], # columns that update allows - select => [qw/name age/], # columns that data returns - prefetch => ['cds'], # relationships that are prefetched when no prefetch param is passed - prefetch_allows => [ # every possible prefetch param allowed + class => 'MyAppDB::Artist', + result_class => 'MyAppDB::ResultSet::Artist', + create_requires => ['name', 'age'], + create_allows => ['nickname'], + update_allows => ['name', 'age', 'nickname'], + update_allows => ['name', 'age', 'nickname'], + select => [qw/name age/], + prefetch => ['cds'], + prefetch_allows => [ 'cds', qw/ cds /, { cds => 'tracks' }, - { cds => [qw/ tracks /] } + { cds => [qw/ tracks /] }, ], - ordered_by => [qw/age/], # order of generated list - search_exposes => [qw/age nickname/, { cds => [qw/title year/] }], # columns that can be searched on via list - data_root => 'data' # defaults to "list" for backwards compatibility - use_json_boolean => 1, # use JSON::Any::true|false in the response instead of strings - return_object => 1, # makes create and update actions return the object + ordered_by => [qw/age/], + search_exposes => [qw/age nickname/, { cds => [qw/title year/] }], + data_root => 'data', + use_json_boolean => 1, + return_object => 1, ); # Provides the following functional endpoints: @@ -180,7 +181,9 @@ generate_rs is used by inflate_request to generate the resultset stored in the c sub generate_rs { - my ($self, $c) = @_; + #my ($self, $c) = @_; + my ($self) = @_; + return $self->stored_result_source->resultset; } @@ -329,7 +332,7 @@ sub object_lookup list's steps are broken up into three distinct methods: L, L, and L. -The goal of this method is to call ->search() on the current_result_set, HashRefInflator the result, and return it in $c->stash->{response}->{$self->data_root}. Please see the individual methods for more details on what actual processing takes place. +The goal of this method is to call ->search() on the current_result_set, change resultset class of the result (if needed), and return it in $c->stash->{$self->stash_key}->{$self->data_root}. Please see the individual methods for more details on what actual processing takes place. If the L config param is defined then the hashes will contain only those columns, otherwise all columns in the object will be returned. L of course supports the function/procedure calling semantics that L. In order to have proper column names in the result, provide arguments in L (which also follows L semantics. Similarly L, L, L and L affect the maximum number of rows returned as well as the ordering and grouping. Note that if select, count, ordered_by or grouped_by request parameters are present then these will override the values set on the class with select becoming bound by the select_exposes attribute. @@ -424,7 +427,7 @@ sub list_format_output my ($self, $c) = @_; my $rs = $c->req->current_result_set->search; - $rs->result_class('DBIx::Class::ResultClass::HashRefInflator'); + $rs->result_class($self->result_class) if $self->result_class; try { @@ -443,7 +446,7 @@ sub list_format_output $output->{$self->total_entries_arg} = $c->req->search_total_entries + 0; } - $c->stash->{response} = $output; + $c->stash->{$self->stash_key} = $output; } catch { @@ -461,7 +464,8 @@ row_format_output is called each row of the inflated output generated from the s sub row_format_output { - my ($self, $c, $row) = @_; + #my ($self, $c, $row) = @_; + my ($self, undef, $row) = @_; return $row; # passthrough by default } @@ -483,7 +487,7 @@ sub item } else { - $c->stash->{response}->{$self->item_root} = $self->each_object_inflate($c, $c->req->get_object(0)->[0]); + $c->stash->{$self->stash_key}->{$self->item_root} = $self->each_object_inflate($c, $c->req->get_object(0)->[0]); } } @@ -791,7 +795,8 @@ insert_object_from_params sets the columns for the object, then calls ->insert sub insert_object_from_params { - my ($self, $c, $object, $params) = @_; + #my ($self, $c, $object, $params) = @_; + my ($self, undef, $object, $params) = @_; my %rels; while (my ($k, $v) = each %{ $params }) { @@ -831,7 +836,8 @@ Performs the actual ->delete on the object sub delete_object { - my ($self, $c, $object) = @_; + #my ($self, $c, $object) = @_; + my ($self, undef, $object) = @_; $object->delete; } @@ -852,25 +858,25 @@ sub end :Private # Check for errors caught elsewhere if ( $c->res->status and $c->res->status != 200 ) { $default_status = $c->res->status; - $c->stash->{response}->{success} = $self->use_json_boolean ? JSON::Any::false : 'false'; + $c->stash->{$self->stash_key}->{success} = $self->use_json_boolean ? JSON::Any::false : 'false'; } elsif ($self->get_errors($c)) { - $c->stash->{response}->{messages} = $self->get_errors($c); - $c->stash->{response}->{success} = $self->use_json_boolean ? JSON::Any::false : 'false'; + $c->stash->{$self->stash_key}->{messages} = $self->get_errors($c); + $c->stash->{$self->stash_key}->{success} = $self->use_json_boolean ? JSON::Any::false : 'false'; $default_status = 400; } else { - $c->stash->{response}->{success} = $self->use_json_boolean ? JSON::Any::true : 'true'; + $c->stash->{$self->stash_key}->{success} = $self->use_json_boolean ? JSON::Any::true : 'true'; $default_status = 200; } unless ($default_status == 200) { - delete $c->stash->{response}->{$self->data_root}; + delete $c->stash->{$self->stash_key}->{$self->data_root}; } elsif($self->return_object && $c->req->has_objects) { my $returned_objects = []; push(@$returned_objects, $self->each_object_inflate($c, $_)) for map { $_->[0] } $c->req->all_objects; - $c->stash->{response}->{$self->data_root} = scalar(@$returned_objects) > 1 ? $returned_objects : $returned_objects->[0]; + $c->stash->{$self->stash_key}->{$self->data_root} = scalar(@$returned_objects) > 1 ? $returned_objects : $returned_objects->[0]; } $c->res->status( $default_status || 200 ); @@ -887,11 +893,18 @@ This only executes if L if set and if there are any objects to a sub each_object_inflate { - my ($self, $c, $object) = @_; + #my ($self, $c, $object) = @_; + my ($self, undef, $object) = @_; return { $object->get_columns }; } +=method_protected serialize + +multiple actions forward to serialize which uses Catalyst::Action::Serialize. + +=cut + # from Catalyst::Action::Serialize sub serialize :ActionClass('Serialize') { } @@ -904,7 +917,14 @@ push_error stores an error message into the stash to be later retrieved by Lstash->{_dbic_crud_errors}}, $params->{message} || 'unknown error' ); + my $error = 'unknown error'; + if (exists $params->{message}) { + $error = $params->{message}; + # remove newline from die "error message\n" which is required to not + # have the filename and line number in the error text + $error =~ s/\n$//; + } + push( @{$c->stash->{_dbic_crud_errors}}, $error); } =method_protected get_errors @@ -962,9 +982,17 @@ Below are explanations for various configuration parameters. Please see Lmodel to get a resultset for this class. MyAppDB::Track for example. +=head3 resultset_class + +Desired resultset class after accessing your model. MyAppDB::ResultSet::Track for example. By default, it's DBIx::Class::ResultClass::HashRefInflator. Set to empty string to leave resultset class without change. + +=head3 stash_key + +Controls where in stash request_data should be stored, and defaults to 'response'. + =head3 data_root -By default, the response data is serialized into $c->stash->{response}->{$self->data_root} and data_root defaults to 'list' to preserve backwards compatibility. This is now configuable to meet the needs of the consuming client. +By default, the response data is serialized into $c->stash->{$self->stash_key}->{$self->data_root} and data_root defaults to 'list' to preserve backwards compatibility. This is now configuable to meet the needs of the consuming client. =head3 use_json_boolean @@ -1057,7 +1085,7 @@ Arguments to pass to L when performing search for L =head3 page -Arguments to pass to L when performing search for L. +Arguments to pass to L when performing search for L. =head1 EXTENDING @@ -1077,8 +1105,8 @@ For example if you wanted create to return the JSON for the newly created object $self->next::method($c); if ($c->req->has_objects) { - # $c->stash->{response} will be serialized in the end action - $c->stash->{response}->{$self->data_root} = [ map { { $_->get_inflated_columns } } ($c->req->all_objects) ] ; + # $c->stash->{$self->stash_key} will be serialized in the end action + $c->stash->{$self->stash_key}->{$self->data_root} = [ map { { $_->get_inflated_columns } } ($c->req->all_objects) ] ; } }