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=bfd50242d957792d97cefe2ba513bbc78497a56c;hp=837fbea0b9df34948e568b7de6ce5c39d87cc9d8;hb=7821bdec3826d11fe878d13859c15d7f2c5b0cfa;hpb=39955b2a7f4bf1d69ba2159159ec40255e67a35c diff --git a/lib/Catalyst/Controller/DBIC/API.pm b/lib/Catalyst/Controller/DBIC/API.pm index 837fbea..bfd5024 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,24 @@ __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', + 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 +180,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; } @@ -374,6 +376,7 @@ sub list =method_protected list_munge_parameters list_munge_parameters is a noop by default. All arguments will be passed through without any manipulation. In order to successfully manipulate the parameters before the search is performed, simply access $c->req->search_parameters|search_attributes (ArrayRef and HashRef respectively), which correspond directly to ->search($parameters, $attributes). Parameter keys will be in already-aliased form. +To store the munged parameters call $c->req->_set_search_parameters($newparams) and $c->req->_set_search_attributes($newattrs). =cut @@ -460,7 +463,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 } @@ -634,7 +638,7 @@ sub validate_object } # check for multiple values - if (ref($value) && !($value == JSON::Any::true || $value == JSON::Any::false)) + if (ref($value) && !(reftype($value) eq reftype(JSON::Any::true))) { require Data::Dumper; die "Multiple values for '${key}': ${\Data::Dumper::Dumper($value)}"; @@ -718,7 +722,7 @@ sub save_object =method_protected update_object_from_params -update_object_from_params iterates through the params to see if any of them are pertinent to relations. If so it calls L with the object, and the relation parameters. Then it calls ->upbdate on the object. +update_object_from_params iterates through the params to see if any of them are pertinent to relations. If so it calls L with the object, and the relation parameters. Then it calls ->update on the object. =cut @@ -729,13 +733,22 @@ sub update_object_from_params foreach my $key (keys %$params) { my $value = $params->{$key}; - if (ref($value) && !($value == JSON::Any::true || $value == JSON::Any::false)) + if (ref($value) && !(reftype($value) eq reftype(JSON::Any::true))) { $self->update_object_relation($c, $object, delete $params->{$key}, $key); } + # accessor = colname + elsif ($object->can($key)) { + $object->$key($value); + } + # accessor != colname + else { + my $accessor = $object->result_source->column_info($key)->{accessor}; + $object->$accessor($value); + } } - $object->update($params); + $object->update(); } =method_protected update_object_relation @@ -748,7 +761,29 @@ sub update_object_relation { my ($self, $c, $object, $related_params, $relation) = @_; my $row = $object->find_related($relation, {} , {}); - $row->update($related_params); + + if ($row) { + foreach my $key (keys %$related_params) { + my $value = $related_params->{$key}; + if (ref($value) && !(reftype($value) eq reftype(JSON::Any::true))) + { + $self->update_object_relation($c, $row, delete $related_params->{$key}, $key); + } + # accessor = colname + elsif ($row->can($key)) { + $row->$key($value); + } + # accessor != colname + else { + my $accessor = $row->result_source->column_info($key)->{accessor}; + $row->$accessor($value); + } + } + $row->update(); + } + else { + $object->create_related($relation, $related_params); + } } =method_protected insert_object_from_params @@ -759,9 +794,24 @@ insert_object_from_params sets the columns for the object, then calls ->insert sub insert_object_from_params { - my ($self, $c, $object, $params) = @_; - $object->set_columns($params); + #my ($self, $c, $object, $params) = @_; + my ($self, undef, $object, $params) = @_; + + my %rels; + while (my ($k, $v) = each %{ $params }) { + if (ref($v) && !(reftype($v) eq reftype(JSON::Any::true))) { + $rels{$k} = $v; + } + else { + $object->set_column($k => $v); + } + } + $object->insert; + + while (my ($k, $v) = each %rels) { + $object->create_related($k, $v); + } } =method_protected delete_objects @@ -785,7 +835,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; } @@ -841,11 +892,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_inflated_columns }; + 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') { } @@ -858,7 +916,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 @@ -1011,7 +1076,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