NAME
App::AutoCRUD - A Plack application for browsing and editing databases
SYNOPSIS
Quick demo
To see the demo distributed with this application :
cd examples/Chinook
plackup app.psgi
Then point your browser to http://localhost:5000.
General startup
Create a configuration file, for example in YAML format, like this :
app:
name: Test AutoCRUD
datasources :
Source1 :
dbh:
connect:
# arguments that will be passed to DBI->connect(...)
# for example :
- dbi:SQLite:dbname=some_file
- "" # user
- "" # password
- RaiseError : 1
sqlite_unicode: 1
Create a file crud.psgi like this :
use App::AutoCRUD;
use YAML qw/LoadFile/;
my $config = LoadFile "/path/to/config.yaml";
my $crud = App::AutoCRUD->new(config => $config);
my $app = $crud->to_app;
Then run the app
plackup crud.psgi
or mount the app in Apache
<Location /crud>
SetHandler perl-script
PerlResponseHandler Plack::Handler::Apache2
PerlSetVar psgi_app /path/to/crud.psgi
</Location>
and use your favorite web browser to navigate through your database.
DESCRIPTION
This module embodies a web application for Creating, Retrieving, Updating and Deleting records in relational databases (hence the 'CRUD' acronym). The 'Auto
' part of the name is because the application automatically generates and immediately uses the components needed to work with your data -- you don't have to edit scaffolding code. The 'Plack
' part of the name comes from the Plack middleware framework used to implement this application.
To connect to one or several databases, just supply a configuration file with the connnection information, and optionally some presentation information, and then you can directly work with the data. Optionally, the configuration file can also specify many additional details, like table groups, column groups, data descriptions, etc. If more customization is needed, then you can modify the presentation templates, or even subclass some parts of the framework.
This application was designed to be easy to integrate with other web resources in your organization : every table, every record, every search form has its own URL which can be linked from other sources, can be bookmarked, etc. This makes it a great tool for example for adding an admin interface to an existing application : just install AutoCRUD at a specific location within your Web server (with appropriate access control :-).
Some distinctive features of this module, in comparison with other CRUD applications, are :
Hyperlinks between records, corresponding to foreign key relationships in the database.
Support for update or delete of several records at once.
Support for reordering, masking, documenting tables and columns through configuration files -- a cheap way to provide reasonable user experience without investing into a full-fledged custom application.
Data export in Excel, YAML, JSON, XML formats
Extensibility through inheritance
This application is also meant as an example for showing the power of "Modern Perl", assembling several advanced frameworks such as Moose, Plack and DBIx::DataModel.
CONFIGURATION
The bare minimum for this application to run is to get some configuration information about how to connect to datasources. This can be done directly in Perl, like in the test file t/00_autocrud.t :
my $connect_options = {
RaiseError => 1,
sqlite_unicode => 1,
};
my $config = {
app => {
name => "SomeName"
},
datasources => {
SomeDatabase => {
dbh => {
connect => [$dbi_connect_string, $user, $passwd, $connect_options],
},
},
},
};
# instantiate the app
my $crud = App::AutoCRUD->new(config => $config);
my $app = $crud->to_app;
With this minimal information, the application will just display tables and columns in alphabetical order. However, the configuration may also specify many details about grouping and ordering tables and columns; in that case, it is more convenient to use an external format like YAML, XML or AppConfig. Here is an excerpt from the YAML configuration for Chinook, a sample database distributed with this application (see the complete example under the examples/Chinook directory within this distribution) :
datasources :
Chinook :
dbh:
connect:
- "dbi:SQLite:dbname=Chinook_Sqlite_AutoIncrementPKs.sqlite"
- ""
- ""
- RaiseError: 1
sqlite_unicode: 1
tablegroups :
- name: Music
descr: Tables describing music content
node: open
tables :
- Artist
- Album
- Track
- name: Playlist
descr: Tables for structuring playlists
node: open
tables :
- Playlist
- PlaylistTrack
...
tables:
Track:
colgroups:
- name: keys
columns:
- name: TrackId
descr: Primary key
- name: AlbumId
descr: foreign key to the album where this track belongs
- name: GenreId
descr: foreign key to the genre of this track
- name: MediaTypeId
descr: foreign key to the media type of this track
- name: Textual information
columns:
- name: Name
descr: name of this track
- name: Composer
descr: name of composer of this track
- name: Technical details
columns:
- name: Bytes
- name: Milliseconds
- name: Commercial details
columns:
- name: UnitPrice
The full datastructure for configuration information is documented in App::AutoCRUD::ConfigDomain.
USAGE
Generalities
All pages are presented with a Tree navigator. Tree sections can be folded/unfolded either through the mouse or through navigation keys LEFT and RIGHT. Keys DOWN and UP navigate to the next/previous sections. Typing the initial characters of a section title directly jumps to that section.
Homepage
The homepage displays the application short name, title, and the list of available datasources.
Schema
The schema page, for a given datasource, displays the list of tables, grouped and ordered according to the configuration (if any).
Each table has an immediate hyperlink to its search form; in addition, another link points to the description page for this table.
Table description
The description page for a given table presents the list of columns, with typing information as obtained from the database, and hyperlinks to other tables for which this table has foreign keys.
Search form
The search form allows users to enter search criteria and presentation parameters.
Search criteria
Within a column input field, one may enter a constant value, a list of values separated by commas, a partial word with an ending star (which will be interpreted as a SQL "LIKE" clause), a comparison operator (ex > 2013
), or a BETWEEN clause (ex BETWEEN 2 AND 6
).
The full syntax accepted for such criteria is documented in SQL::Abstract::FromQuery. That syntax is customizable, so if you want to support additional fancy operators for your database, you might do so by augmenting or subclassing the grammar.
Columns to display
On the right of each column input field is a checkbox to decide if this column should be displayed in the results or not. If the configuration specifies column groups, each column group also has a checkbox to simultaneously check all columns in that group. Finally, there is also a global checkbox to check/uncheck everything. If nothing is checked (which is the default), this will be implicitly interpreted as "SELECT *", i.e. showing everything.
Presentation parameters
Presentation parameters include :
pagination information (page size / page index)
output format, which is one of :
Flag for total page count (this is optional because it is not always important, and on many databases it has an additional cost as it requires an additional call to the database to know the total number of records).
List page
The list page displays a list of records resulting from a search. The generated SQL is shown for information. For columns that related to other tables, there are hyperlinks to the related lists.
Each record has a checkbox for marking this record for update or delete.
Hyperlinks to the next/previous page are provided, but navigation through pages can also be performed with the LEFT/RIGHT arrow keys.
Single record display
The single record page is very similar to the list page, but only displays one single record. The only difference is in the hyperlinks to update/delete/clone operations.
Update
The update page has two modes : single-record or multiple-records
Single-record update
The form shows current values on the right, and has input fields on the left. Only fields with some user input will be sent for update to the database.
Multiple-records update
This form is reached from the "List page", when several records were checked, or when updating the whole result set.
Input fields on the left correspond to the SQL "SET
" clause, i.e. they specify values that will be updated within several records simultaneously.
Input fields on the right, labelled "where/and", specify some criteria for the SQL "WHERE
" clause.
Needless to say, this is quite a powerful operation which if misused could easily corrupt your data.
Delete
Like updates, delete forms can be either single-record or multiple-records.
Insert
The insert form is very much like the single-record update form, except that there are no "current values"
Clone
The clone form is like an insert form, but pre-filled with the data to clone, except the primary key which is always empty.
ARCHITECTURE
[to be developed]
Classes
Modules are organized in a classical Model-View-Controller structure.
Inheritance and customization
All classes can be subclassed, and the application will automatically discover and load appropriate modules on demand. Presentation templates can also be overridden in sub-applications.
DataModel
This application requires a DBIx::DataModel::Schema subclass for every datasource. If none is supplied, a subclass will be generated and loaded on the fly; but this incurs an additional startup cost, and does not exploit all possibilities of DBIx::DataModel; so apart from short demos and experiments, it is better to statically generate a schema and store it in a file.
An initial schema class can be built, either from a DBI database handle, or from an existing DBIx::Class schema; see DBIx::DataModel::Schema::Generator.
ATTRIBUTES
config
A datatree of information, whose structure should comply with App::AutoCRUD::ConfigDomain.
name
The application name (displayed in most pages). This attribute defaults to the value of the app/name
entry in config.
datasources
A hashref of the datasources served by this application. Hash keys are unique identifiers for the datasources (these names will also be used to generate URIs); hash values are instances of the App::AutoCRUD::DataSource class.
dir
The root directory where some application components could be placed (like for example some presentation templates).
This attribute defaults to the value of the dir
entry in config, or, if absent, to the current directory.
This directory is associated with the application instance. When components are not found in this directory, they are searched in the directories associated with the application classes (see the share_path
attribute below).
share_paths
An arrayref to a list of directories corresponding to the hierarchy of application classes. These directories are searched as second resort, when components are not found in the application instance directory.
readonly
A boolean to restrict actions available to only read from the database. The value of readonly boolean is set in YAML configuration file.
METHODS
new
my $crud_app = App::AutoCRUD->new(%options);
Creates a new instance of the application. All attributes described above may be supplied as %options
.
datasource
my $datasource = $app->datasource($name);
Returnes the the datasource registered under the given name.
call
This method implements request dispatch, as required by the Plack middleware.
config
my $data = $app->config(@path);
Walks through the configuration tree, following node names as specified in @path
, and returns whatever is found at the end of this path ( either a subtree, or scalar data, or undef
if the path leads to nothing ).
try_load_class
my $class = $self->try_load_class($name, $namespace);
Invokes "load_class" in Plack::Util; returns the loaded class in case of success, or undef
in case of failure.
find_class
my $class = $app->find_class($subclass_name);
Tries to find the given $subclass_name
within the namespaces of the application classes.
is_class_loaded
Checks if the given class is already loaded in memory or not.
CAVEATS
In the current implementation, the slash charater ('/'
) is interpreted as a separator for primary keys over multiple columns. This means that an embedded slash in a column name or in the value of a primary key could yield unexpected results. This is definitely something to be improved in a future versions, but at the moment I still don't know how it will be solved.
ACKNOWLEDGEMENTS
Some design aspects were borrowed from
AUTHOR
Laurent Dami, <dami at cpan.org>
SUPPORT
You can find documentation for this module with the perldoc command.
perldoc App::AutoCRUD
You can also look for information at:
github's request tracker (report bugs here)
MetaCPAN
The source code is at https://github.com/damil/App-AutoCRUD.
SEE ALSO
Catalyst::Plugin::AutoCRUD, WebAPI::DBIC, Plack, http://www.codeplex.com/ChinookDatabase.
TODO
- column properties
- noinsert, noupdate, nosearch, etc.
- edit: select or autocompleter for foreign keys
- internationalisation
-
- View:
- default view should be defined in config
- overridable content-type & headers
- search form, show associations => link to join search
- list foreign keys even if not in DBIDM schema
- change log
- quoting problem (FromQuery: "J&B")
- readonly fields: tabindex -1 (can be done by CSS?)
in fact, current values should NOT be input fields, but plain SPANs
- NULL in updates
- Update form, focus problem (focus in field should deactivate TreeNav)
- add insert link in table descr
- deal with Favicon.ico
- declare in http://www.sqlite.org/cvstrac/wiki?p=ManagementTools
- multicolumns : if there is an association over a multicolumns key,
it is not displayed as a hyperlink in /list. To do so, we would need
to add a line in the display, corresponding to the multicolumn.
LICENSE AND COPYRIGHT
Copyright 2014-2021 Laurent Dami.
This program is free software; you can redistribute it and/or modify it under the terms of the the Artistic License (2.0). You may obtain a copy of the full license at: