File Coverage

blib/lib/WebAPI/DBIC.pm
Criterion Covered Total %
statement 6 6 100.0
branch n/a
condition n/a
subroutine 2 2 100.0
pod n/a
total 8 8 100.0


line stmt bran cond sub pod time code
1             package WebAPI::DBIC;
2             $WebAPI::DBIC::VERSION = '0.004001';
3 2     2   3040426 use strict; # keep our kwalitee up!
  2         48  
  2         144  
4 2     2   17 use warnings;
  2         1  
  2         155  
5              
6              
7             1;
8              
9             __END__
10              
11             =pod
12              
13             =encoding UTF-8
14              
15             =head1 NAME
16              
17             WebAPI::DBIC
18              
19             =head1 VERSION
20              
21             version 0.004001
22              
23             =head1 DESCRIPTION
24              
25             WebAPI::DBIC (or "WAPID" for short) provides the parts you need to build a
26             feature-rich RESTful JSON web service API backed by DBIx::Class schemas.
27              
28             WebAPI::DBIC features include:
29              
30             * Built as fine-grained roles for maximum reusability and extensibility.
31              
32             * Integrates with other L<Plack> based applications.
33              
34             * The resource roles can be added to your existing application.
35              
36             * Built on the strong foundations of L<Plack> and L<Web::Machine>, plus
37             L<Path::Router> as the router. (Other routers could be supported.)
38              
39             * Rich support for multiple hypermedia types, including ActiveModel / Ember-Data
40             (C<application/json>), JSON API (C<application/vnd.api+json>)
41             and HAL (C<application/hal+json>).
42             The Collection+JSON and JSON-LD hypermedia types could be added in future.
43              
44             * Automatic detection and exposure of result set relationships.
45              
46             * Supports safe robust multi-related-record CRUD transactions.
47              
48             * An example .psgi file that gives you an instant web service for any
49             DBIx::Class schema.
50              
51             * A generic pure-javascript HAL API browser application is integrated with
52             WebAPI::DBIC so you can be browsing your new API in seconds.
53              
54             =head2 Media Types Supported
55              
56             The HTTP C<Content-Type> and C<Accept> headers are used to specify
57             the 'media type' of a request, and the desired response. In the case of JSON
58             types, the media type defines not only that the content is a JSON data structure,
59             but the semantics (meaning) of the the scructure.
60              
61             A single application can support requests and responses in multiple media
62             types, using the headers to negotiate the right behaviour for ech request.
63              
64             =head3 ActiveModel
65              
66             Designed to match the behaviour of the active_model_serializers Ruby gem
67             and thus be directly usable as a backend for frameworks compatible with it,
68             including Ember. This uses the C<application/json> media type. (This is a very
69             common 'default' media type for web data services.)
70              
71             See L<WebAPI::DBIC::Resource::ActiveModel> for more information.
72              
73             =head3 HAL
74              
75             The Hypertext Application Language hypermedia type (or HAL for short)
76             is a simple JSON format that gives a consistent and easy way to hyperlink
77             between resources in your API. It uses the C<application/hal+json> media type.
78              
79             A pure-JavaScript "HAL Browser" application is integrated with the WebAPI::DBIC
80             distribution via the L<Alien::Web::HalBrowser> module. It's a great way to
81             explore your API.
82              
83             See L<http://stateless.co/hal_specification.html> for more details of the specification.
84             See L<WebAPI::DBIC::Resource::HAL> for more details of WebAPI::DBIC support.
85              
86             =head3 JSON API
87              
88             The JSON API media type is designed to minimize both the number of requests and
89             the amount of data transmitted between clients and servers. This efficiency is
90             achieved without compromising readability, flexibility, and discoverability.
91             It's an (as yet immature) evolution of the ActiveModel media type.
92              
93             See L<WebAPI::DBIC::Resource::JSONAPI> for more details.
94              
95             =head3 WAPID
96              
97             The WebAPI::DBIC core and tests use the C<application/vnd.wapid+json> media
98             type. It's subject to change without notice.
99              
100             =head2 Web::Machine
101              
102             The L<Web::Machine> module provides a RESTful web framework modeled as a formal
103             state machine. This is a rigorous and powerful approach, originally developed
104             in Erlang and since ported to many other languages.
105             See L<https://raw.githubusercontent.com/basho/webmachine/develop/docs/http-headers-status-v3.png>
106             for an image of the state machine.
107              
108             By building on Web::Machine, WebAPI::DBIC removes the need to implement all the
109             logic needed for accurate and full-featured HTTP protocol behaviour.
110             You just provide small pieces of logic at the decision points you care about
111             and Web::Machine looks after the rest.
112             See L<https://github.com/basho/webmachine/wiki> for more information.
113              
114             Web::Machine provides the logic to handle a HTTP request for a I<single resource>.
115             With WebAPI::DBIC those resources typically represent a DBIx::Class result set,
116             a row, or a method invocation on a row or result set. They are implemented as a subclass of
117             L<Web::Machine::Resource> that consumes a some set of WebAPI::DBIC roles which add
118             the desired functionality to the resource.
119              
120             =head2 Path::Router
121              
122             The L<Path::Router> module is used to organize multiple resources into a URL
123             namespace. It's used to route incoming requests to the appropriate Web::Machine
124             instance. It's also used in reverse to construct links to other resources that
125             are included in the outgoing responses.
126              
127             Path::Router supports full reversability: the value produced by a path match
128             can be passed back in and you will get the same path you originally put in.
129             This removes ambiguity and reduces mis-routings. This is important for
130             WebAPI::DBIC because, for each resource returned, it automatically add HAL
131             C<_links> containing the URLs of the related resources, as defined by the
132             DBIx::Class schema. This is what makes the API discoverable and browseable.
133              
134             =head1 NAME
135              
136             WebAPI::DBIC - A composable RESTful JSON API to DBIx::Class schemas using roles and Web::Machine
137              
138             =head1 STATUS
139              
140             The WebAPI::DBIC code has been in production use since early 2013, however it's
141             only recently been open sourced (July 2014) so it's still lacking in documentation.
142             It's also undergoing a period of refactoring, enhancement and evolution now
143             there are more developers contributing and the code is being applied to more domains.
144              
145             Interested? Please get involved! See L</HOW TO GET HELP> below.
146              
147             =head1 QUICK START
148              
149             To demonstrate the rich functionality that the combination of DBIx::Class and
150             HAL provides, the WebAPI::DBIC framework includes a ready-to-use L<Plack> .psgi
151             file that provides an instant web data service for any DBIx::Class schema.
152              
153             $ git clone https://github.com/timbunce/WebAPI-DBIC.git
154             $ cd WebAPI-DBIC
155             $ cpanm Module::CPANfile
156             $ cpanm --installdeps . # this may take a while
157              
158             $ export WEBAPI_DBIC_SCHEMA=DummyLoadedSchema
159             $ plackup -Ilib -It/lib webapi-dbic-any.psgi
160             ... open a web browser on port 5000 to browse the API
161              
162             Then try it out with your own schema:
163              
164             $ export WEBAPI_DBIC_SCHEMA=Foo::Bar # your own schema
165             $ export WEBAPI_DBIC_HTTP_AUTH_TYPE=none # recommended
166             $ export DBI_DSN=dbi:Driver:... # your own database
167             $ export DBI_USER=... # for initial connection, if needed
168             $ export DBI_PASS=... # for initial connection, if needed
169             $ plackup -Ilib webapi-dbic-any.psgi
170             ... open a web browser on port 5000 to browse your new API
171              
172             The API is read-only by default. To enable PUT, POST, DELETE etc, set the
173             C<WEBAPI_DBIC_WRITABLE> environment variable.
174              
175             =head1 MODULES
176              
177             =head2 Core Roles
178              
179             L<WebAPI::DBIC::Resource::Role::DBIC> is responsible for interfacing with
180             L<DBIx::Class>, 'rendering' individual records as resource data structures.
181             It also interfaces with Path::Router to handle relationship linking.
182              
183             L<WebAPI::DBIC::Resource::Role::Set> is responsible for accepting GET and HEAD
184             requests for set resources (collections) and returning the results as JSON.
185              
186             L<WebAPI::DBIC::Resource::Role::SetWritable> is responsible for accepting POST
187             request for set resources. It handles the recursive creation of related records.
188             Related records can be nested to any depth and are created from the bottom up
189             within a transaction.
190              
191             L<WebAPI::DBIC::Resource::Role::Item> is responsible for GET and HEAD requests
192             for single item resources and returning the results as JSON.
193              
194             L<WebAPI::DBIC::Resource::Role::ItemWritable> is responsible for accepting PUT
195             and DELETE requests for single item resources. It handles the recursive update of
196             related records. Related records can be nested to any depth and are updated
197             from the bottom up within a transaction. Handles both 'PUT is replace' and
198             'PUT is update' logic.
199              
200             L<WebAPI::DBIC::Resource::Role::ItemInvoke> is responsible for accepting POST
201             requests for single item resources representing the invocation of a specific
202             method on an item (e.g. POST /widget/42/invoke/my_method_name?args=...).
203              
204             L<WebAPI::DBIC::Resource::Role::SetInvoke> is responsible for accepting POST
205             requests for set resources representing the invocation of a specific
206             method on a result set (e.g. POST /widget/invoke/my_method_name?args=...).
207              
208             L<WebAPI::DBIC::Resource::Role::DBICAuth> is responsible for checking
209             authorization to access a resource. It currently supports Basic Authentication,
210             using the DBI DSN as the realm name and the return username and password as the
211             username and password for the database connection.
212              
213             L<WebAPI::DBIC::Resource::Role::DBICParams> is responsible for handling request
214             parameters related to DBIx::Class such as C<page>, C<rows>, C<sort>, C<me>,
215             C<prefetch>, C<fields> etc.
216              
217             =head2 ActiveModel Roles
218              
219             For support of the C<application/json> media type, see L<WebAPI::DBIC::Resource::ActiveModel>.
220              
221             =head2 JSON+HAL Roles
222              
223             See L<WebAPI::DBIC::Resource::HAL>
224              
225             =head2 JSON API Roles
226              
227             See L<WebAPI::DBIC::Resource::JSONAPI>
228              
229             =head2 Utility Roles
230              
231             L<WebAPI::DBIC::Role::JsonEncoder> provides encode_json() and decode_json() methods.
232              
233             L<WebAPI::DBIC::Role::JsonParams> provides a param() method that returns query
234             parameters, except that any parameters with names that have a C<~json> suffix
235             have their values JSON decoded, so they can be arbitrary data structures.
236              
237             =head2 Resource Classes
238              
239             To make building typical applications easier, WebAPI::DBIC provides several
240             pre-defined resource classes:
241              
242             L<WebAPI::DBIC::Resource::GenericCore> is a base class that consumes all the
243             general-purpose resource roles.
244              
245             L<WebAPI::DBIC::Resource::GenericSet> subclasses GenericCore and consumes extra
246             roles for resources represented by a DBIx::Class result set.
247              
248             L<WebAPI::DBIC::Resource::GenericItem> subclasses GenericCore and consumes
249             extra roles for resources represented by an individual DBIx::Class row.
250              
251             L<WebAPI::DBIC::Resource::GenericSetInvoke> subclasses GenericCore and
252             consumes extra roles for resources that represent a specific method call on a
253             set resource.
254              
255             L<WebAPI::DBIC::Resource::GenericItemInvoke> subclasses GenericCore and
256             consumes extra roles for resources that represent a specific method call on an
257             item resource.
258              
259             These classes are I<very> simple because all the work is done by the various
260             roles they consume. For example, here's the entire code for
261             L<WebAPI::DBIC::Resource::GenericCore>:
262              
263             package WebAPI::DBIC::Resource::GenericCore;
264             use Moo;
265             extends 'WebAPI::DBIC::Resource::Base';
266             with 'WebAPI::DBIC::Role::JsonEncoder',
267             'WebAPI::DBIC::Role::JsonParams',
268             'WebAPI::DBIC::Resource::Role::Router',
269             'WebAPI::DBIC::Resource::Role::Identity',
270             'WebAPI::DBIC::Resource::Role::Relationship',
271             'WebAPI::DBIC::Resource::Role::DBIC',
272             'WebAPI::DBIC::Resource::Role::DBICException',
273             'WebAPI::DBIC::Resource::Role::DBICAuth',
274             'WebAPI::DBIC::Resource::Role::DBICParams',
275             ;
276             1;
277              
278             and L<WebAPI::DBIC::Resource::GenericItem>:
279              
280             package WebAPI::DBIC::Resource::GenericSet;
281             use Moo;
282             extends 'WebAPI::DBIC::Resource::GenericCore';
283             with 'WebAPI::DBIC::Resource::Role::Set',
284             'WebAPI::DBIC::Resource::Role::SetWritable',
285             ;
286             1;
287              
288             =head2 Other Classes
289              
290             A few other classes are provided:
291              
292             L<WebAPI::DBIC::Util.pm> provides a few general utilities.
293              
294             L<WebAPI::DBIC::WebApp> - this is the main app class and is most likely to
295             change in the near future so isn't documented much yet.
296              
297             =head1 TRANSPARENCY
298              
299             WebAPI::DBIC aims to be a fairly 'transparent' layer between your
300             L<DBIx::Class> schema and the JSON that's generated and received.
301              
302             So it's the responibility of your schema to return data in the format you want
303             in your generated URLs and JSON, and to accept data in the format that arrives
304             in requests from clients.
305              
306             For an example of how to handle dates using L<DateTime> nicely, see:
307              
308             https://blog.afoolishmanifesto.com/posts/solution-on-how-to-serialize-dates-nicely/
309              
310             =head1 COMPARISONS
311              
312             This section provides links to similar modules with a few notes about how they
313             differ from WebAPI::DBIC.
314              
315             =head2 ... others? ...
316              
317             =head2 App::AutoCRUD
318              
319             L<App::AutoCRUD> provides an automatically generated I<HTML> interface to a
320             database, including search forms. It can export data in various formats
321             including JSON but isn't designed as a JSON API, so it's not directly
322             comparable to WebAPI::DBIC. See also L<RapidApp>.
323              
324             App::AutoCRUD doesn't use DBIx::Class, it uses DBIx::DataModel (a UML-based ORM
325             framework), but creates the model on the fly. That doesn't let you build
326             business logic into the schema model the way you can with DBIx::Class.
327              
328             =head2 RapidApp
329              
330             To quote the documentation: L<RapidApp> is an extension to L<Catalyst> - the
331             Perl MVC framework. It provides a feature-rich extended development stack, as
332             well as easy access to common out-of-the-box application paradigms, such as
333             powerful CRUD-based front-ends for DBIx::Class models, user access and
334             authorization, RESTful URL navigation schemes, pure Ajax interfaces with no
335             browser page loads, templating engine with front-side CMS features, declarative
336             configuration layers, and more.
337              
338             It's not designed as a JSON API and doesn't use HAL, so it's not directly
339             comparable to WebAPI::DBIC.
340              
341             =head1 INTEGRATIONS
342              
343             This section provides information on how to integrate WebAPI::DBIC with
344             existing applications.
345              
346             =head2 Catalyst
347              
348             As with any PSGI application, WebAPI::DBIC can integrate into Catalyst fairly
349             simply with L<Catalyst::Action::FromPSGI>. Here's an example integration:
350              
351             package MyApp::Controller::HelloName;
352              
353             use base 'Catalyst::Controller';
354              
355             sub api : Path('/api') ActionClass('FromPSGI') {
356             my ($self, $c) = @_;
357              
358             WebAPI::DBIC::WebApp->new({
359             schema => $c->model('DB')->schema,
360             ...
361             })->to_psgi_app
362             }
363              
364             =head2 Dancer
365              
366             I<I'd welcome any information you could contribute here.>
367              
368             =head2 Mojolicious
369              
370             I<I'd welcome any information you could contribute here.>
371              
372             =head2 ...
373              
374             =head1 HOW TO GET HELP
375              
376             =over
377              
378             =item * IRC: irc.perl.org#webapi
379              
380             =for html <a href="https://chat.mibbit.com/#webapi@irc.perl.org">(click for instant chatroom login)</a>
381              
382             =for comment =item * RT Bug Tracker: L<https://rt.cpan.org/NoAuth/Bugs.html?Dist=WebAPI-DBIC>
383              
384             =item * Source: L<https://github.com/timbunce/WebAPI-DBIC>
385              
386             =back
387              
388             See also https://metacpan.org/pod/distribution/WebAPI-DBIC/NOTES.pod
389             and https://github.com/timbunce/WebAPI-DBIC/issues
390              
391             If there's anything you specifically need, just ask!
392              
393             =head1 CREDITS
394              
395             Stevan Little gets top billing for creating L<Web::Machine> and L<Path::Router>
396             (not to mention L<Moose> and much else besides).
397              
398             Matt Trout and Peter Rabbitson and the rest of the L<DBIx::Class> team for
399             creating and maintaining such an excellent object <-> relational mapper.
400              
401             Arthur Axel "fREW" Schmidt, both for his original "drinkup" prototype using
402             Web::Machine that WebAPI::DBIC is based on, and for offering to help with the
403             work required to open source and release WebAPI::DBIC to CPAN. Without that,
404             and further help from Fitz Elliott, WebAPI::DBIC might still be a closed source
405             internal project.
406              
407             =head1 OVERVIEW OF REPRESENTIONS AND ACTIONS
408              
409             The docs below are from old internal documentation. They're a bit rought and
410             will be reworked and found a better home. They're here for now because they are
411             useful to give a sense of how the API works and what it supports.
412              
413             =head2 GENERIC ENTITY REPRESENTIONS
414              
415             Here we define the default behavior for GET, PUT, DELETE and POST methods on
416             item and set resources.
417              
418             In these examples the ~ symbol is used to represent a common prefix. The
419             prefix is intended to contain at least a single path name element plus a
420             version number element, for example, in:
421              
422             GET ~/ecosystems/
423              
424             the ~ represents a prefix such as "/clients/v1", so the above is a shorthand
425             way of representing:
426              
427             GET /clients/v1/ecosystems/
428              
429             =head3 Conventions
430              
431             Resource names are typically plural nouns, and lower case, with underscores if required.
432             Verbs could be used for for non-resource requests and might be capitalized (e.g. /Convert?from=Y&to=Y).
433              
434             A parameter that's part of the url is represented in these examples with the
435             :name convention, e.g. :id.
436              
437             XXX That might change to the 'URL Template' RFC6570 style
438             http://tools.ietf.org/html/rfc6570
439              
440             =head2 GET Item
441              
442             GET ~/resources/:id
443              
444             returns
445              
446             {
447             _links: { ... } # optional
448             _embedded: { ... } # optional
449             _meta: { ... } # optional
450             ... # data attributes, optional
451             }
452              
453             The optional _links object holds relevant links in the HAL format
454             (see below). This enables interactive browsing of the API.
455              
456             The optional _embedded object holds embedded resources in the HAL format.
457             (see L</prefetch>).
458              
459             The optional _meta attribute might include things like the name of the
460             attribute to treat as the label, or a count of items matching a search.
461              
462             GET ~/ecosystems/1
463              
464             would include
465              
466             {
467             id: 1,
468             ...
469             person_id: 2, # foreign key
470             ...
471             _links {
472             self: {
473             href: "/ecosystems/1"
474             },
475             "relation:person": {
476             href: /person/19
477             },
478             "relation:email_domain": {
479             href: "/email_domain/8"
480             }
481             },
482             }
483              
484             The "relation" links describe the relationships this resource has with other resources.
485              
486             Also see L</prefetch>.
487              
488             =head2 GET Item - Optional Parameters
489              
490             =head3 prefetch
491              
492             Prefetch is a mechanism in DBIx::Class by which related resultsets can be returned
493             along with the primary resultset. This prefetching is performed by a single query and
494             so improves efficiency by reducing the number of database requests.
495              
496             In WebAPI::DBIC the C<prefetch> parameter enables use of DBIx::Class prefetch and
497             so allows any data in related resultsets to be returned as part of the same
498             response. This allows the user to make one GET to return most, and possibly all,
499             of the data needed by the requesting application. This reduces the number of HTTP requests.
500              
501             Note that prefetch is only effective for response types that support embedded
502             data, e.g, C<application/hal+json>.
503              
504             Prefetching in WebAPI::DBIC and DBIx::Class uses the accessor names defined in the
505             Result class for the given Resultset. These should be used in the prefetch parameter.
506              
507             The following examples assume a Schema setup similar to the following:
508              
509             package MyApp::Schema::Result::Artist;
510             __PACKAGE__->has_many('albums' => 'MyApp::Schema::Result::CD', 'album_artist');
511             __PACKAGE__->has_many('cd_artists' => 'MyApp::Schama::Result::CDArtist', 'artistid');
512             __PACKAGE__->belongs_to('producer' => 'MyApp::Schema::Result::Producer', 'producerid');
513             __PACKAGE__->many_to_many('cds' => 'cd_artists', 'cd');
514              
515             package MyApp::Schema::Result::CD;
516             __PACKAGE__->has_many('cd_artists' => 'MyApp::Schema::Result::CDArtist', 'cdid');
517             __PACKAGE__->belongs_to('album_artist' => 'MyApp::Schema::Result::Artist', 'album_artist');
518             __PACKAGE__->many_to_many('artists' => 'cd_artists', 'artist');
519              
520             package MyApp::Schema::Result::CDArtists;
521             __PACKAGE__->belongs_to('cd' => 'MyApp::Schema::Result::CD', 'cdid');
522             __PACKAGE__->belongs_to('artist' => 'MyApp::Schema::Result::Artist', 'artistid');
523              
524             =head4 comma seperated lists
525              
526             Where all related data for individual directly related resultsets are desired
527             then a comma seperated list can be provided to the the prefetch parameter
528              
529             artist/1?prefetch=producer,albums
530              
531             (Note that you can't provide the prefetch parameter multiple times to achieve
532             the same result.)
533              
534             This would return the following JSON+HAL:
535              
536             {
537             artistid: 1,
538             producerid: 1,
539             _embedded: {
540             producer: {
541             producer: id,
542             },
543             albums: [{
544             cdid: 1,
545             album_artist: 1,
546             },{
547             cdid: 2,
548             album_artist: 1,
549             }],
550             },
551             _links: {
552             producer: /producer/1,
553             albums: /artists/1?albums~json={-or: [{cdid: 1}, {cdid: 2}]} # XXX not correct
554             }
555             }
556              
557             =head4 json
558              
559             The C<prefetch> parameter can be specified as a more complex JSON-encoded
560             parameter value. This allows for the full use of prefetch chains.
561             Using key value pairs and lists, prefetches can be nested from one resultset to
562             another:
563              
564             artist/1?prefetch~json={["producer","albums"]}
565              
566             This would produce the same results as above:
567              
568             artist/1?prefetch~json={["producer","cd_artists",{"cds":"album_artist"}]}
569              
570             would producer the following JSON+HAL:
571              
572             {
573             artistid: 1,
574             producerid: 1,
575             _embedded: {
576             producer: {
577             producer: id,
578             },
579             cd_artists: [{
580             artistsid: 1,
581             cdid: 1,
582             _embedded: {
583             cd: {
584             cdid: 1,
585             album_artist: 1,
586             _embedded: {
587             album_artist: {
588             artistid: 1,
589             producerid: 1,
590             },
591             },
592             _links: {
593             /album_artist: /artist/1
594             },
595             },
596             },
597             _links: {
598             cd: /cd/1
599             },
600             }],
601             },
602             _links: {
603             producer: /producer/1,
604             cd_artists: /cdartists?artistid=1&cdid=1,
605             }
606             }
607              
608             NOTE: many_to_many relationships can't be supported as they are not true relationships
609             the related data should be prefetched using the has_many relationship and their join
610             table as in the above example.
611              
612             =head4 where on prefetch
613              
614             The WHERE clause generated can filter results based on related data, as you
615             would expect in a SQL style JOIN. To refer to fields in related resultsets,
616             prefix the name of the field with the name of the relationship:
617              
618             /artist?prefetch=albumns&albums.title='My CD Title'
619              
620             This would return all artists which have an album with the title 'My CD Title'.
621              
622             =head3 fields
623              
624             The fields parameter can be used to limit the fields returned in the response.
625             For example:
626              
627             fields=field1,field2
628              
629             This also works
630             in combination with the prefetch parameter. As with querying on prefetched relations, the
631             relation accessor should be appended before the field name in question.
632              
633             /artist/1?prefetch=albums&fields=artistid,albumns.title
634              
635             For more information on PREFETCHING and JOINS see L<DBIx::Class::Resultset#PREFETCHING>
636              
637             NOTE: DBIx::Class does not support the returning of related data if the relationship
638             accessor for that data matches a column on the requested Set or Item but the fields
639             parameter does not include that column. You must explicitly request fields if prefetching
640             a relation with the same name
641              
642             Using the above example. If the artist has a producer column/field then the following is
643             invalid:
644              
645             /artist/1?prefetch=producer&fields=artistid,producer.producer.producerid
646              
647             but the following is valid:
648              
649             /artist/1?prefetch=producer&fields=artistid,producer,producer.producer.producerid
650              
651             =head3 with
652              
653             The C<with> parameter is used to control optional items within responses. It's
654             a comma separated list of words. This parameter is only passed-through in paging links.
655              
656             * B<count>
657              
658             Adds a C<count> attribute to the C<_meta> hash in the results containing the
659             count of items in the set matched by the request, i.e., the number of items
660             that would be returned if paging was disabled. Also adds a C<last> link to the
661             C<_links> section of the results.
662              
663             * B<nolinks>
664              
665             TBD - possibly used to disable links in the results, especially for large sets
666             of small items where the links section would take significant time and space to
667             construct and return. Might be better as a linkdepth=N where N is decremented
668             at each level of embedding so linkdepth=0 disables all links, but linkdepth=1
669             allows paging of the set but doesn't include links in the embedded resources.
670              
671             =head2 GET on Set
672              
673             GET ~/ecosystems
674              
675             returns
676              
677             {
678             _links: { ... }, # optional
679             _meta: { ... }, # optional
680             _embedded: {
681             ecosystems => [
682             { ... }, ...
683             ]
684             }
685             }
686              
687             The _embedded object contains a key matching the resource name whoose
688             value is an array of those resources, in HAL format. It may seem unusual that
689             the response isn't simply an array of the resources, but you can think of the
690             'set' as a 'virtual' entity that I<contains nothing itself> but just acts as a
691             container, or view, for a set of I<embedded resources>.
692              
693             The _links objects would include links in HAL format for first/prev/next/last.
694              
695             The _meta could include attributes like limit, offset.
696              
697             =head2 GET on Set - Optional Parameters
698              
699             =head3 Paging
700              
701             Set results are returned in pages to prevent accidentally trying to
702             fetch very large numbers of rows. The default is a small number.
703              
704             rows=N - default 30 (at the time of writing)
705             page=N - default 1
706              
707             =head3 fields
708              
709             Partial results, as for GET Item above.
710              
711             =head3 Sorting and Ordering
712              
713             sort=field1
714             sort=field1,-field2
715              
716             A comma-separated list of one or more ordering clauses. Each clause consists of a
717             field designator with an optional C<-> prefix to indicate descending order
718             instead of ascending.
719              
720             Field names can refer to fields of L</prefetch> relations. For example:
721              
722             ~/ecosystems_people?prefetch=person,client_auth&sort=client_auth.username
723              
724             The parameter name C<order> can be used as a deprecated alias for C<sort>.
725             The direction can also be specified by appending either "C< asc>" or "C< desc>"
726             to the field designator. This syntax is deprecated.
727              
728             =head3 Filtering
729              
730             ?me.fieldname=value
731              
732             Filtering with query params
733              
734             ?me.color=red&me.state=running
735              
736             The me.*= values can be JSON data structures if the field name is sufixed with
737             ~json, for example:
738              
739             ?me.color~json=["red","blue"] # would actually be URL encoded
740              
741             which would be evaluated as an SQL 'IN' expression:
742              
743             color IN ('red', 'blue')
744              
745             More complex expressions can be expressed using hashes, for example:
746              
747             ?me.color~json={"like":"%red%"} # would actually be URL encoded
748              
749             would be evaluated as
750              
751             color LIKE '%red%'
752              
753             and
754              
755             ?me.foo~json=[ "-and", {"!=":2}, {"!=":1} ] # shown unencoded
756              
757             would be evaluated as
758              
759             foo != 2 and foo != 1
760              
761             See https://metacpan.org/module/SQL::Abstract#WHERE-CLAUSES for more examples.
762              
763             The me.* parameters are only passed-through in paging links.
764              
765             =head3 Prefetching Related Objects
766              
767             ?prefetch=person,client_auth
768              
769             The resource may have 1-1 and 1-N relationships with other resources.
770             (E.g., "belongs_to" and "has_many" relationships in DBIx::Class terminology.)
771              
772             The relevant instances of related resources can be fetched and returned along
773             with the requested resource by listing the relationships in a prefetch parameter.
774              
775             For example: GET /ecosystems_people?prefetch=person,client_auth
776              
777             {
778             "_links": { ... },
779             "_embedded": {
780             "ecosystems_people": [
781             {
782             "client_auth_id": "29",
783             "person_id": "8",
784             ...
785             "_links": { ... },
786             "_embedded": {
787             "client_auth": { # embedded client_auth resourse
788             "id": 29
789             ...
790             },
791             "person": { # embedded person resourse
792             "id": 8,
793             ...
794             }
795             },
796             },
797             ... # next ecosystems_people resource
798             ]
799             }
800             }
801              
802             =head3 distinct
803              
804             distinct=1
805              
806             Only return distinct results.
807              
808             Currently this parameter requires that both the fields and sort parameters are
809             provided, and have identical values.
810              
811             The results are returned in HAL format, i.e., as an array of objects in an
812             _embedded field, but the objects themselves are not in HAL format, i.e. they
813             don't have _links or _embedded elements.
814              
815             =head2 PUT on Item
816              
817             Update resource attributes using the JSON attribute values in the request body.
818              
819             Embedded related resources can be supplied (if the Content-Type is C<application/hal+json>).
820              
821             Changes will be made in a single transaction.
822              
823             Prefetch of related resources is supported.
824              
825             TODO Enable use of the ETag header for optimistic locking?
826              
827             =head2 PUT on Set
828              
829             Not supported.
830              
831             =head2 DELETE on Item
832              
833             Delete the record.
834              
835             =head2 DELETE on Set
836              
837             Not supported.
838              
839             =head2 POST on Item
840              
841             Not supported.
842              
843             =head2 POST on Set
844              
845             Create a new resource in the set. Returns a 302 redirect with a Location
846             header giving the URL of the newly created resource.
847              
848             Any attributes that aren't specified in the POST data will be given the default
849             values specified by the database schema.
850              
851             The C<prefetch> parameter can be used to request that the created resource
852             (C<prefetch=self>) and any related resources, be returned in the body of the
853             response.
854              
855             The rollback=1 parameter let's you rollback a POST to a set, e.g., for testing.
856              
857             TBD check that only fields valid for GET have been supplied
858              
859             =head2 Creating Related Resources
860              
861             If the Content-Type is C<application/hal+json> then related resources can be
862             provided via the C<_embedded> attribute. They will be created first and the
863             corresponding key fields of the main resource will be set to the appropriate
864             values before it's inserted. All database changes will happen in a single transaction.
865              
866             For example, given a POST to /albums containing:
867              
868             {
869             name: "album name",
870             artist_id: null, # optional
871             _embedded => {
872             artist => {
873             name: "artist name",
874             }
875             }
876             }
877              
878             The artist resource would be created first and its primary key would be
879             used to set the artist_id field before that was created.
880              
881             This process works recursively for any number of level and any number of
882             relations at each level.
883              
884             =head2 Errors
885              
886             Error status responses should include a JSON object with at least these fields:
887              
888             {
889             status: NNN,
890             message: "...",
891             }
892              
893             XXX Needs to be extended to be able to express errors related to specific
894             attributes in the request.
895              
896             The above is out of date. XXX review work on JSON media types for error
897             reporting (I recall there's one that has adopted HAL).
898              
899             =head2 Invoking Methods
900              
901             To enable the execution of functionality not covered by the general HTTP
902             mechanisms described above, it's possible to define resources that represent
903             arbitary methods. These methods are executed by a POST request to the
904             correponding resource. The body of the request contains the parameters to the
905             method.
906              
907             Currently a method can only be invoked on an item resource. The resource for
908             the method call is simply the url of the item resource with '/invoke/:method'
909             appended:
910              
911             POST ~/ecosystems/:id/invoke/:method
912              
913             The request supports the same query parameters as the corresponding item
914             resource.
915              
916             =head3 Default Argument and Response Handling
917              
918             Custom method resources can be defined which can perform any desired action,
919             argument and response handling.
920              
921             A default behaviour is provided to handle simple cases, and that is what is
922             described here.
923              
924             The named method is invoked on the item object specified by the item resource.
925             In other words, the method is a method in the schema's Result class.
926              
927             The POST request must use content-type of application/json and, if arguments
928             are required, are specified via an 'args' element in the body JSON:
929              
930             { args => [ ... ] }
931              
932             The method is called in a scalar context.
933              
934             If the method returns a DBIx::Class::Row object it is returned as a JSON hash.
935              
936             If the method returns a DBIx::Class ResultSet object it is returned as a JSON
937             array containing a hash for every row in the result set. There is no paging.
938              
939             If the method returns any other kind of value it it returned as a JSON hash
940             containing a single element 'result':
941              
942             { result: ... }
943              
944             (To avoid attempting to serialize objects, if the result is blessed then it's
945             stringified.)
946              
947             Note that this default behaviour is liable to change. If you want to make
948             method calls like this you should define your own resource based on the one provided.
949              
950             =head1 AUTHOR
951              
952             Tim Bunce <Tim.Bunce@pobox.com>
953              
954             =head1 COPYRIGHT AND LICENSE
955              
956             This software is copyright (c) 2015 by Tim Bunce.
957              
958             This is free software; you can redistribute it and/or modify it under
959             the same terms as the Perl 5 programming language system itself.
960              
961             =cut