File Coverage

blib/lib/Catalyst/Plugin/AutoCRUD.pm
Criterion Covered Total %
statement 13 71 18.3
branch 0 20 0.0
condition 0 3 0.0
subroutine 5 7 71.4
pod n/a
total 18 101 17.8


line stmt bran cond sub pod time code
1             package Catalyst::Plugin::AutoCRUD;
2             {
3             $Catalyst::Plugin::AutoCRUD::VERSION = '2.200001';
4             }
5              
6 1     1   54407 use strict;
  1         4  
  1         62  
7 1     1   7 use warnings;
  1         2  
  1         40  
8              
9 1     1   1089 use MRO::Compat;
  1         3922  
  1         50  
10 1     1   790 use Devel::InnerPackage qw/list_packages/;
  1         3977  
  1         1321  
11              
12             our $this_package = __PACKAGE__; # so it can be used in hash keys
13             our $VERSION ||= '0.00031412';
14              
15             sub setup_components {
16 0     0     my $class = shift;
17 0           $class->next::method(@_);
18              
19             # these are the boilerplate Catalyst components for AutoCRUD
20 0           my @packages = qw(
21             Controller::Root
22             Controller::Static
23             Controller::AJAX
24             Controller::DisplayEngine::ExtJS2
25             Controller::DisplayEngine::Skinny
26             Model::StorageEngine::DBIC
27             View::JSON
28             View::TT
29             );
30              
31             # will auto-load other models, so this one is not -required-
32 0 0         if (exists $class->config->{'Model::AutoCRUD::DBIC'}) {
33 0           push @packages, 'Model::DBIC';
34 0           my $p = 'Model::AutoCRUD::DBIC';
35              
36             # on the fly schema engineering
37 0 0         if (!exists $class->config->{$p}->{schema_class}) {
38 0           require DBIx::Class::Schema::Loader;
39 0 0         die "Must have DBIx::Class::Schema::Loader version > 0.04005"
40             if eval "$DBIx::Class::Schema::Loader::VERSION" <= 0.04005;
41              
42 0           DBIx::Class::Schema::Loader::make_schema_at(
43             'AutoCRUD::Loader::Schema', {naming => 'current'},
44             $class->config->{$p}->{connect_info},
45             );
46              
47 0           eval q{
48             package # hide from the PAUSE
49             AutoCRUD::Loader::Schema;
50             use base 'DBIx::Class::Schema';
51             AutoCRUD::Loader::Schema->load_classes();
52             1;
53             };
54 0           $INC{'AutoCRUD/Loader/Schema.pm'} = 'loaded';
55              
56 0           $class->config->{$p}->{schema_class} = 'AutoCRUD::Loader::Schema';
57             }
58             }
59              
60             # bodge the config for chained PathPart so the user can use our basepath
61             # shortcut in their config, which is less verbose than Cat's alternative
62 0           (my $config_key = $this_package) =~ s/^Catalyst:://;
63 0 0 0       if (exists $class->config->{$config_key}
64             and exists $class->config->{$config_key}->{basepath}) {
65 0           $class->config->{'Controller::AutoCRUD::Root'}->{action}->{base}->{PathPart}
66             = $class->config->{$config_key}->{basepath};
67             }
68              
69             # any additional backends requested
70 0 0         if (exists $class->config->{$config_key}->{backends}) {
71 0           my @backends = ref $class->config->{$config_key}->{backends} eq ref ''
72             ? $class->config->{$config_key}->{backends}
73 0 0         : @{ $class->config->{$config_key}->{backends} };
74              
75             # they will be componentized below
76 0           push @packages, map {'Model::StorageEngine::' . $_} @backends;
  0            
77              
78             # this so that they can be forwarded to in the controller
79 0           my %m = map {('Model::AutoCRUD::StorageEngine::' . $_) => 1} @backends;
  0            
80 0           ++$m{'Model::AutoCRUD::StorageEngine::DBIC'};
81 0           $class->config->{$config_key}->{backends} = [ keys %m ];
82             }
83             else {
84 0           $class->config->{$config_key}->{backends} =
85             [ 'Model::AutoCRUD::StorageEngine::DBIC' ];
86             }
87              
88 0           foreach my $orig (@packages) {
89 0           (my $p = $orig) =~ s/::/::AutoCRUD::/;
90 0           my $comp = "${class}::${p}";
91              
92             # require will shortcircuit and return true if the component is
93             # already loaded
94 0 0         unless (eval "package $class; require $comp;") {
95              
96             # make a component on the fly in the App namespace
97 0           eval qq(
98             package $comp;
99             use base qw/${this_package}::${orig}/;
100             1;
101             );
102 0 0         die $@ if $@;
103              
104             # inject entry to %INC so Perl knows this component is loaded
105             # this is just for politeness and does not aid Catalyst
106 0           (my $file = "$comp.pm") =~ s{::}{/}g;
107 0           $INC{$file} = 'loaded';
108              
109             # add newly created components to catalyst
110             # must set up component and -then- call list_packages on it
111 0           $class->components->{$comp} = $class->setup_component($comp);
112 0           for my $m (list_packages($comp)) {
113 0           $class->components->{$m} = $class->setup_component($m);
114             }
115             }
116             }
117              
118 0           return 1;
119             }
120              
121             # we subvert the pretty print error screen for dumpmeta
122             sub dump_these {
123 0     0     my $c = shift;
124              
125 0           my $params = {
126 0           map {$_ => $c->stash->{$_}}
127 0           grep {ref $c->stash->{$_} eq ''}
128 0           grep {$_ =~ m/^cpac_/}
129 0           keys %{$c->stash},
130             };
131              
132             # strip the SQLT objects
133 0           my $meta = undef;
134 0 0         if (exists $c->stash->{cpac}->{m}) {
135 0           $meta = scalar $c->stash->{cpac}->{m}->extra;
136 0           foreach my $t (values %{$c->stash->{cpac}->{m}->t}) {
  0            
137 0           $meta->{t}->{$t->name} = scalar $t->extra;
138 0           foreach my $f (values %{$t->f}) {
  0            
139 0           $meta->{t}->{$t->name}->{f}->{$f->name} = scalar $f->extra;
140             }
141             }
142             }
143              
144 0 0         if ($c->stash->{dumpmeta}) {
145             return (
146 0           [ 'CPAC Parameters (cpac_*)' => $params ],
147             [ 'Global Configuration (g)' => $c->stash->{cpac}->{g} ],
148             [ 'Site Configuration (c)' => $c->stash->{cpac}->{c} ],
149             [ 'Storage Metadata (m)' => $meta ],
150             [ 'Response' => $c->response ], # only to pacify log_request
151             );
152             }
153 0           else { $c->next::method(@_) }
154             }
155              
156             # monkey patch Catalyst::View::JSON until it is fixed, or users will get scared
157             # by the warning currently emitted by Catalyst
158              
159 1     1   396 use Catalyst::View::JSON;
  0            
  0            
160             my $json_new = _get_subref('new', 'Catalyst::View::JSON');
161             {
162             no warnings 'redefine';
163             *Catalyst::View::JSON::new = sub {
164             delete $_[2]->{catalyst_component_name};
165             goto $json_new;
166             };
167             }
168              
169             sub _get_subref {
170             my $sub = shift;
171             my $pkg = shift || scalar caller(0);
172              
173             my $symtbl = \%{main::};
174             foreach my $part(split /::/, $pkg) {
175             $symtbl = $symtbl->{"${part}::"};
176             }
177              
178             return eval{ \&{ $symtbl->{$sub} } };
179             }
180              
181             1;
182              
183             # ABSTRACT: Instant AJAX web front-end for DBIx::Class
184              
185              
186             __END__
187             =pod
188              
189             =head1 NAME
190              
191             Catalyst::Plugin::AutoCRUD - Instant AJAX web front-end for DBIx::Class
192              
193             =head1 VERSION
194              
195             version 2.200001
196              
197             =head1 STATUS
198              
199             B<Important Notice>
200              
201             This distribution is no longer under active maintenance. The status of
202             AutoCRUD is now "pull-request" only, meaning there will only be updates when
203             the author receives a patch or pull request (via Github).
204              
205             You are recommended to take a look at the excellent L<RapidApp> distributiuon
206             and in particular the L<rdbic.pl> script which can do the same thing as
207             AutoCRUD (only better, and maintained).
208              
209             =head1 PURPOSE
210              
211             You have a database, and wish to have a basic web interface supporting Create,
212             Retrieve, Update, Delete and Search, with little effort. This module is able
213             to create such interfaces on the fly. They are a bit whizzy and all Web
214             2.0-ish.
215              
216             =over 4
217              
218             =item *
219              
220             See the demo at: L<http://demo.autocrud.pl/>
221              
222             =back
223              
224             =head1 SYNOPSIS
225              
226             If you already have a L<Catalyst> app with L<DBIx::Class> models configured:
227              
228             use Catalyst qw(AutoCRUD); # <-- add the plugin name here in MyApp.pm
229              
230             Now load your app in a web browser, but add C</autocrud> to the URL path.
231              
232             Alternatively, to connect to an external database if you have the DBIX::Class
233             schema available, use the C<ConfigLoader> plugin with the following config:
234              
235             <Model::AutoCRUD::DBIC>
236             schema_class My::Database::Schema
237             connect_info dbi:Pg:dbname=mydbname;host=mydbhost.example.com;
238             connect_info username
239             connect_info password
240             <connect_info>
241             AutoCommit 1
242             </connect_info>
243             </Model::AutoCRUD::DBIC>
244              
245             If you don't have the DBIx::Class schema available, just omit the
246             C<schema_class> option (and have L<DBIx::Class::Schema::Loader> installed).
247              
248             =head1 DESCRIPTION
249              
250             This module contains an application which will automatically construct a web
251             interface for a database on the fly. The web interface supports Create,
252             Retrieve, Update, Delete and Search operations.
253              
254             The interface is not written to static files on your system, and uses AJAX to
255             act upon the database without reloading your web page (much like other
256             Web 2.0 applications, for example Google Mail).
257              
258             Almost all the information required by the plugin is retrieved from the
259             L<DBIx::Class> ORM frontend to your database, which it is expected that you
260             have already set up (although see L</USAGE>, below). This means that any
261             change in database schema ought to be reflected immediately in the web
262             interface after a page refresh.
263              
264             =head1 USAGE
265              
266             =head2 Read Me First
267              
268             =over 4
269              
270             =item *
271              
272             If you get stuck, read the
273             L<Troubleshooting|Catalyst::Plugin::AutoCRUD::Manual::Troubleshooting> documentation.
274              
275             =item *
276              
277             L<DBIx::Class> users should read
278             L<DBIx::Class Tips|Catalyst::Plugin::AutoCRUD::Manual::DBICTips>.
279              
280             =item *
281              
282             This plugin provides no user-based access authentication or authorization.
283             Please take care when deploying, and consider who will have access. It is
284             possible to restrict the add/update/delete operations on data. See L</TIPS
285             AND TRICKS> for other suggestions.
286              
287             =back
288              
289             =head2 Scenario 1: Plugin to an existing Catalyst App
290              
291             This mode is for when you have written your Catalyst application, but the
292             Views are catering for the users and as an admin you'd like a more direct,
293             secondary web interface to the database.
294              
295             package AutoCRUDUser;
296             use Catalyst qw(AutoCRUD);
297            
298             __PACKAGE__->setup;
299             1;
300              
301             Adding C<Catalyst::Plugin::AutoCRUD> as a plugin to your Catalyst application,
302             as above, causes it to scan your existing Models. If any of them are built
303             using L<Catalyst::Model::DBIC::Schema>, they are automatically loaded.
304              
305             This mode of operation works even if you have more than one database. You will
306             be offered a Home screen to select the database, and then another menu to
307             select the table within that.
308              
309             Remember that the pages available from this plugin will be located under the
310             C</autocrud> path of your application. Use the C<basepath> option if you want
311             to override this.
312              
313             =head2 Scenario 2: Frontend for an existing C<DBIx::Class::Schema> based class
314              
315             In this mode, C<Catalyst::Plugin::AutoCRUD> is running standalone, in a sense
316             as the Catalyst application itself. Your main application file looks almost
317             the same as in Scenario 1, except you'll need the C<ConfigLoader> plugin:
318              
319             package AutoCRUDUser;
320             use Catalyst qw(ConfigLoader AutoCRUD);
321            
322             __PACKAGE__->setup;
323             1;
324              
325             For the configuration, you need to tell AutoCRUD which package contains the
326             C<DBIx::Class> schema, and also provide database connection parameters.
327              
328             <Model::AutoCRUD::DBIC>
329             schema_class My::Database::Schema
330             connect_info dbi:Pg:dbname=mydbname;host=mydbhost.example.com;
331             connect_info username
332             connect_info password
333             <connect_info>
334             AutoCommit 1
335             </connect_info>
336             </Model::AutoCRUD::DBIC>
337              
338             The C<Model::AutoCRUD::DBIC> section must look (and be named) exactly like that
339             above, except you should of course change the C<schema_class> value and the
340             values within C<connect_info>.
341              
342             Remember that the pages available from this plugin will be located under the
343             C</autocrud> path if your application. Use the C<basepath> option if you want
344             to override this.
345              
346             =head3 C<DBIx::Class> setup
347              
348             You will of course need the C<DBIx::Class> schema to be created and installed
349             on your system. The recommended way to do this quickly is to use the excellent
350             L<DBIx::Class::Schema::Loader> module which connects to your database and
351             writes C<DBIx::Class> Perl modules for it.
352              
353             Pick a suitable namespace for your schema, which is not related to this
354             application. For example C<DBIC::Database::Foo::Schema> for the C<Foo>
355             database (in the configuration example above we used C<My::Database::Schema>).
356             Then use the following command-line incantation:
357              
358             perl -MDBIx::Class::Schema::Loader=make_schema_at,dump_to_dir:. -e \
359             'make_schema_at("DBIC::Database::Foo::Schema", { debug => 1, naming => 'current' }, \
360             ["dbi:Pg:dbname=foodb;host=mydbhost.example.com","user","pass" ])'
361              
362             This will create a directory (such as C<DBIC>) which you need to move into
363             your Perl Include path (one of the paths shown at the end of C<perl -V>).
364              
365             =head2 Scenario 3: Lazy loading a C<DBIx::Class> schema
366              
367             If you're in such a hurry that you can't create the C<DBIx::Class> schema, as
368             shown in the previous section, then C<Catalyst::Plugin::AutoCRUD> is able to
369             do this on the fly, but it will slow the application's startup just a little.
370              
371             The application file and configuration are very similar to those in Scenario
372             two, above, except that you omit the C<schema_class> configuration option
373             because you want AutoCRUD to generate that on the fly (rather than reading an
374             existing one from disk).
375              
376             package AutoCRUDUser;
377             use Catalyst qw(ConfigLoader AutoCRUD);
378            
379             __PACKAGE__->setup;
380             1;
381              
382             <Model::AutoCRUD::DBIC>
383             connect_info dbi:Pg:dbname=mydbname;host=mydbhost.example.com;
384             connect_info username
385             connect_info password
386             <connect_info>
387             AutoCommit 1
388             </connect_info>
389             </Model::AutoCRUD::DBIC>
390              
391             When AutoCRUD loads it will connect to the database and use the
392             L<DBIx::Class::Schema::Loader> module to reverse engineer its schema. To work
393             properly you'll need the very latest version of that module (at least 0.05,
394             or the most recent development release from CPAN).
395              
396             The other drawback to this scenario (other than the slower operation) is that
397             you have no ability to customize how foreign, related records are shown. A
398             related record will simply be represented as something approximating the name
399             of the foreign table, the names of the primary keys, and associated values
400             (e.g. C<id(5)>).
401              
402             =head1 TIPS AND TRICKS
403              
404             =head2 Displaying Unicode
405              
406             It is essential that you load the L<Catalyst::Plugin::Unicode::Encoding>
407             plugin to ensure proper decoding/encoding of incoming request parameters and
408             the outgoing body response respectively. This is done in your C<MyApp.pm>:
409              
410             use Catalyst qw/ -Debug ConfigLoader Unicode::Encoding AutoCRUD /;
411              
412             Additionally, when connecting to the database, add a flag to the connection
413             parameters, specific to your database engine, that enables Unicode. See the
414             following link for more details:
415              
416             =over 4
417              
418             =item *
419              
420             L<https://metacpan.org/module/DBIx::Class::Manual::Cookbook#Using-Unicode>
421              
422             =back
423              
424             =head2 Representing related records
425              
426             When the web interface wants to display a column which references another
427             table, you can make things look much better by adding a custom render method
428             to your C<DBIx::Class> Result Classes (i.e. the class files for each table).
429              
430             First, the plugin will look for a method called C<display_name> and use that.
431             Here is an example which could be added to your Result Class files below the
432             line which reads C<DO NOT MODIFY THIS OR ANYTHING ABOVE>, and in this case
433             returns the data from the C<title> column:
434              
435             sub display_name {
436             my $self = shift;
437             return $self->title || '';
438             }
439              
440             Failing the existence of a C<display_name> method, the plugin attempts to
441             stringify the row object. Using stringification is not recommended, although
442             some people like it. Here is an example of a stringification handler:
443              
444             use overload '""' => sub {
445             my $self = shift;
446             return $self->title || '';
447             }, fallback => 1;
448              
449             If all else fails the plugin prints the best hint it can to describe the
450             foreign row. This is something approximating the name of the foreign table,
451             the names of the primary keys, and associated values. It's better than
452             stringifying the object the way Perl does, anyway.
453              
454             =head2 Textfields and Textareas
455              
456             When the plugin creates a web form for adding or editing, it has to choose
457             whether to show a Textfield or Textarea for text-type fields. If you have set
458             a C<size> option in add_columns() within the Schema, and this is less than or
459             equal to 40, a Textfield is used. Otherwise, if the C<size> option is larger
460             than 40 or not set, then an auto-expanding, scrollable Textarea is used.
461              
462             =head2 Column names with spaces
463              
464             The plugin will handle most tricky names, but you should remember to pass some
465             required extra quoting hints to DBIx::Class when it makes a connection to your
466             database:
467              
468             # most databases:
469             { quote_char => q{`}, name_sep => q{.} }
470            
471             # SQL Server:
472             { quote_char => [qw/[ ]/], name_sep => q{.} }
473              
474             For more information see the L<DBIx::Class::Storage::DBI> manual page or ask
475             on the DBIx::Class mail list.
476              
477             =head2 Database IO filters
478              
479             Buried within one of the modules in this application are some filters which
480             are applied to data of certain types as it enters or leaves the database. If
481             you find a particular data type is not being rendered correctly, please drop
482             the author a line at the email address below, explaining what you'd like to
483             see instead.
484              
485             =head2 Relocating AutoCRUD to another URL path
486              
487             If you want to use this application as a plugin with another Catalyst system,
488             it should work fine, but you probably want to serve pages under a different
489             path on your web site. To that end, the plugin by default places its pages
490             under a path part of C<...E<sol>autocrudE<sol>>. You can change this by adding
491             the following option to your configuration file:
492              
493             <Plugin::AutoCRUD>
494             basepath admin
495             </Plugin::AutoCRUD>
496              
497             In the above example, the path C<...E<sol>adminE<sol>> will contain the AutoCRUD
498             application, and all generated links in AutoCRUD will also make use of that path.
499             Remember this is added to the C<base> of your Cataylst application which,
500             depending on your web server configuration, might also have a leading path.
501              
502             To have the links based at the root of your application (which was the default
503             behaviour of C<CatalystX::ListFramework::Builder>, set this variable to an
504             empty string in your configuration:
505              
506             <Plugin::AutoCRUD>
507             basepath ""
508             </Plugin::AutoCRUD>
509              
510             =head2 Using your own ExtJS libraries
511              
512             The plugin will use copies of the ExtJS libraries hosted in the CacheFly
513             content delivery network out there on the Internet. Under some circumstances
514             you'll want to use your own hosted copy, for instance if you are serving HTTPS
515             (because browsers will warn about mixed HTTP and HTTPS content).
516              
517             In which case, you'll need to download the ExtJS Javascript Library (version
518             2.2+ recommended), from this web page:
519             L<http://www.sencha.com/products/extjs/download/>.
520              
521             Install it to your web server in a location that it is able to serve as static
522             content. Make a note of the path used in a URL to retrieve this content, as it
523             will be needed in the application configuration file, like so:
524              
525             <Plugin::AutoCRUD>
526             extjs2 /static/javascript/extjs-2
527             </Plugin::AutoCRUD>
528              
529             Use the C<extjs2> option as shown above to specify the URL path to the
530             libraries. This will be used in the templates in some way like this:
531              
532             <script type="text/javascript" src="[% c.config.extjs2 %]/ext-all.js" />
533              
534             =head2 Changing the HTML Character Set
535              
536             The default HTML C<charset> used by this module is C<utf-8>. If you wish to override
537             this, then set the C<html_charset> parameter, as below:
538              
539             <Plugin::AutoCRUD>
540             html_charset iso-8859-1
541             </Plugin::AutoCRUD>
542              
543             =head2 Simple read-only non-JavaScript Frontend
544              
545             All table views will default to the full-featured ExtJS based frontend. If you
546             would prefer to see a simple read-only non-JavaScript interface, then append
547             C</browse> to your URL.
548              
549             This simpler frontend uses HTTP GET only, supports paging and sorting, and
550             will obey any column filtering and renaming as set in your L</"SITES CONFIGURATION"> file.
551              
552             =head2 Overriding built-in Templates
553              
554             The whole site is built from Perl Template Toolkit templates, and it is
555             possible to override these shipped templates with your own files. This goes
556             for both general files (CSS, top-level TT wrapper) as well as the site files
557             mentioned in the next section.
558              
559             To add these override paths, include the following directive in your
560             configuration file:
561              
562             <Plugin::AutoCRUD>
563             tt_path /path/to/my/local/templates
564             </Plugin::AutoCRUD>
565              
566             This C<tt_path> directive can be included multiple times to set a list of
567             override paths, which will be processed in the order given.
568              
569             Within the specified directory you should mirror the file structure where the
570             overridden templates have come from, including the frontend name. For example:
571              
572             extjs2
573             extjs2/wrapper
574             extjs2/wrapper/footer.tt
575             skinny
576             skinny/wrapper
577             skinny/wrapper/footer.tt
578              
579             If you want to override any of the CSS used in the app, copy the C<head.tt>
580             template from whichever C<site> you are using, edit, and install in a local
581             C<tt_path> set with this directive.
582              
583             =head2 Reconfiguring Embedded Plugins
584              
585             Embedded plugins such as L<Catalyst::View:TT>, L<Catalyst::View::JSON>, etc,
586             can be reconfigured in your C<myapp.yml> file using a simple naming
587             convention. Remove the leading "Catalyst", and insert "AutoCRUD" after the
588             first namespace component. For example:
589              
590             View::AutoCRUD::TT:
591             ENCODING: utf-8
592              
593             Note that this does not affect your own App's usage of the same plugins, only
594             the AutoCRUD plugin's instances are reconfigured.
595              
596             =head1 SITES CONFIGURATION
597              
598             It's possible to have multiple views of the source data, tailored in various
599             ways. For example you might choose to hide some tables, or columns within
600             tables, rename headings of columns, or disable updates or deletes.
601              
602             This is all achieved through the C<sites> configuration. Altering the default
603             site simply allows for control of column naming, hiding, etc. Creating a new
604             site allows you to present alternate configurations of the same source data.
605              
606             =head2 Altering the Default Site
607              
608             When using this plugin out of the box you're already running within the
609             default site, which unsurprisingly is called C<default>. To override settings
610             in this, create the following configuration stub, and fill it in with any of
611             the options listed below:
612              
613             <Plugin::AutoCRUD>
614             <sites>
615             <default>
616             # override settings here
617             </default>
618             </sites>
619             </Plugin::AutoCRUD>
620              
621             =head2 Configuration Options for Sites
622              
623             In general, when you apply a setting to something at a higher level (say, a
624             database), it I<percolates> down to the child sections (i.e. the tables). For
625             example, setting C<delete_allowed no> on a database will prevent records from
626             any table within that from being deleted.
627              
628             Some of the options are I<global> for a site, others apply to the database or
629             table within it. To specify an option for one or the other, use the database
630             and table names I<as they appear in the URL path>:
631              
632             <Plugin::AutoCRUD>
633             <sites>
634             <default>
635             # global settings for the site, here
636             <mydb>
637             # override settings here
638             <sometable>
639             # and/or override settings here
640             </sometable
641             </mydb>
642             </default>
643             </sites>
644             </Plugin::AutoCRUD>
645              
646             =head3 Options
647              
648             =over 4
649              
650             =item update_allowed [ yes* | no ]
651              
652             This can be applied to either a database or a table; if applied to a database it
653             percolates to all the tables, unless the table has a different setting.
654              
655             The default is to allow updates to be made to existing records. Set this to a
656             value of C<no> to prevent this operation from being permitted. Widgets will
657             also be removed from the user interface so as not to confuse users.
658              
659             <Plugin::AutoCRUD>
660             <sites>
661             <default>
662             update_allowed no
663             </default>
664             </sites>
665             </Plugin::AutoCRUD>
666              
667             =item create_allowed [ yes* | no ]
668              
669             This can be applied to either a database or a table; if applied to a database it
670             percolates to all the tables, unless the table has a different setting.
671              
672             The default is to allow new records to be created. Set this to a value of
673             C<no> to prevent this operation from being allowed. Widgets will also be
674             removed from the user interface so as not to confuse users.
675              
676             <Plugin::AutoCRUD>
677             <sites>
678             <default>
679             create_allowed no
680             </default>
681             </sites>
682             </Plugin::AutoCRUD>
683              
684             =item delete_allowed [ yes* | no ]
685              
686             This can be applied to either a database or a table; if applied to a database it
687             percolates to all the tables, unless the table has a different setting.
688              
689             The default is to allow deletions of records in the tables. Set this to a
690             value of C<no> to prevent deletions from being allowed. Widgets will also be
691             removed from the user interface so as not to confuse users.
692              
693             <Plugin::AutoCRUD>
694             <sites>
695             <default>
696             delete_allowed no
697             </default>
698             </sites>
699             </Plugin::AutoCRUD>
700              
701             =item columns \@column_names
702              
703             This option achieves two purposes. First, you can re-order the set of columns
704             as they are displayed to the user. Second, by omitting columns from this list
705             you can hide them from the main table views.
706              
707             Provide a list of the column names (as the data source knows them) to this
708             setting. This option must appear at the table level of your site config
709             hierarchy. In C<Config::General> format, this would look something like:
710              
711             <Plugin::AutoCRUD>
712             <sites>
713             <default>
714             <mydb>
715             <thetable>
716             columns id
717             columns title
718             columns length
719             </thetable>
720             </mydb>
721             </default>
722             </sites>
723             </Plugin::AutoCRUD>
724              
725             Any columns existing in the table, but not mentioned there, will not be
726             displayed in the main table. They'll still appear in the record edit form, as
727             some fields are required by the database schema so cannot be hidden. Columns
728             will be displayed in the same order that you list them in the configuration.
729              
730             =item headings { col => title, ... }
731              
732             You can alter the title given to any column in the user interface, by
733             providing a hash mapping of column names (as the data source knows them) to
734             titles you wish displayed to the user. This option must appear at the table
735             level of your site config hierarchy. In C<Config::General> format, this would
736             look something like:
737              
738             <Plugin::AutoCRUD>
739             <sites>
740             <default>
741             <mydb>
742             <thetable>
743             <headings>
744             id Key
745             title Name
746             length Time
747             </headings>
748             </thetable>
749             </mydb>
750             </default>
751             </sites>
752             </Plugin::AutoCRUD>
753              
754             Any columns not included in the hash mapping will use the default title (i.e.
755             what the plugin works out for itself). To hide a column from view, use the
756             C<columns> option, described above.
757              
758             =item hidden [ yes | no* ]
759              
760             If you don't want a database to be offered to the user, or likewise a particular
761             table, then set this option to C<yes>. By default, all databases and tables are
762             shown in the user interface.
763              
764             <Plugin::AutoCRUD>
765             <sites>
766             <default>
767             <mydb>
768             <secrettable>
769             hidden yes
770             </secrettable>
771             </mydb>
772             </default>
773             </sites>
774             </Plugin::AutoCRUD>
775              
776             This can be applied to either a database or table; if applied to a database it
777             overrides all child tables, B<even if> a table has a different setting.
778              
779             =item frontend [ extjs2 | skinny | ... ]
780              
781             With this option you can swap out the set of templates used to generate the
782             web front-end, and completely change its look and feel.
783              
784             Currently you have two choices: either C<extjs2> which is the default and
785             provides the standard full-featured ExtJS2 frontend, or C<skinny> which is a
786             read-only non-JavaScript alternative supporting listing, paging and sorting
787             only.
788              
789             Set the frontend in your site config at its top level. Note that you cannot
790             set the frontend on a per-database or per-table basis, only per-site:
791              
792             <Plugin::AutoCRUD>
793             <sites>
794             <default>
795             frontend skinny
796             </default>
797             </sites>
798             </Plugin::AutoCRUD>
799              
800             Be aware that setting the frontend to C<skinny> does B<not> restrict create or
801             update access to your database via the AJAX API. For that, you still should
802             set the C<*_allowed> options listed above, as required.
803              
804             =back
805              
806             =head2 Creating a New Site
807              
808             You can create a new site by adding it to the C<sites> section of your
809             configuration:
810              
811             <Plugin::AutoCRUD>
812             <sites>
813             <mysite>
814             # local settings here
815             </mysite>
816             </sites>
817             </Plugin::AutoCRUD>
818              
819             You'll notice that a non-default site is active because the path in your URLs
820             changes to a more RPC-like verbose form, mentioning the site, database and
821             table:
822              
823             from this:
824             .../autocrud/mydb/thetable # (i.e. site == default)
825            
826             to this:
827             .../autocrud/site/mysite/schema/mydb/source/thetable
828              
829             So let's say you've created a dumbed down site for your users which is
830             read-only (i.e. C<update_allowed no> and C<delete_allowed no>), and called the
831             site C<simplesite> in your configuration. You need to give the following URL
832             to users:
833              
834             .../autocrud/site/simplesite
835              
836             You could also then place an access control on this path part in your web
837             server (e.g. Apache) which is different from the default site itself.
838              
839             =head1 INSTANT DEMO APPLICATIONS
840              
841             =head2 Automagic Loading
842              
843             If you want to run an instant demo of this module, with minimal configuration,
844             then a simple application for that is shipped with this distribution. For this
845             to work, you must have:
846              
847             =over 4
848              
849             =item *
850              
851             The very latest version of L<DBIx::Class::Schema::Loader> installed on your
852             system (at least 0.05, or the most recent release from CPAN).
853              
854             =item *
855              
856             SQLite3 and the accompanying DBD module, if you want to use the shipped demo
857             database.
858              
859             =back
860              
861             Go to the C<examples/sql/> directory of this distribution and run the
862             C<bootstrap_sqlite.pl> perl script. This will create an SQLite file.
863              
864             Now change to the C<examples/demo/> directory and start the demo application
865             like so:
866              
867             demo> perl ./server.pl
868              
869             Visit C<http://localhost:3000> in your browser as instructed at the end of
870             the output from this command.
871              
872             To use your own database rather than the SQLite demo, edit
873             C<examples/demo/demo.conf> so that it contains the correct C<dsn>, username,
874             and password for your database. Upon restarting the application you should see
875             your own data source instead.
876              
877             =head2 Row Display Names
878              
879             An alternate application exists which demonstrates use of the C<display_name>
880             method on a L<DBIx::Class> Row, to give row entries "friendly names". Follow
881             all the instructions above but instead run the following server script:
882              
883             demo> perl ./server_with_display_name.pl
884              
885             =head2 Other Features
886              
887             Finally, the kitchen sink of other features supported by this module are
888             demonstrated in a separate application. This contains many tables, each of
889             which highlights one or more aspects of a relational database backend being
890             rendered in AutoCRUD.
891              
892             Follow all the instructions above, but instead run the following server
893             script:
894              
895             demo> perl ./server_other_features.pl
896              
897             =head1 TROUBLESHOOTING
898              
899             See L<Catalyst::Plugin::AutoCRUD::Manual::Troubleshooting>.
900              
901             =head1 LIMITATIONS
902              
903             See L<Catalyst::Plugin::AutoCRUD::Manual::Limitations>.
904              
905             =head1 SEE ALSO
906              
907             L<CatalystX::CRUD> and L<CatalystX::CRUD:YUI> are two distributions which
908             allow you to create something similar but with full customization, and the
909             ability to add more features. So, you trade effort for flexibility and power.
910              
911             =head1 ACKNOWLEDGEMENTS
912              
913             Without the initial work on C<CatalystX::ListFramework> by Andrew Payne and
914             Peter Edwards this package would not exist. If you are looking for something
915             like this module but without the dependency on Javascript, please do check
916             out L<CatalystX::ListFramework>.
917              
918             =head1 AUTHOR
919              
920             Oliver Gorwits <oliver@cpan.org>
921              
922             =head1 COPYRIGHT AND LICENSE
923              
924             This software is copyright (c) 2015 by Oliver Gorwits.
925              
926             This is free software; you can redistribute it and/or modify it under
927             the same terms as the Perl 5 programming language system itself.
928              
929             =cut
930