DBIx::Class, Catalyst, CRUD, AJAX (and other buzzw 2008-08-06 13:01 oliver
Okay, there are a few things which do a similar job in Perl; a couple of abandonware Catalyst applications, or frameworks which require you to write templates, but what I mean is the whole shebang - Database to ORM to Templates to Web Page, all from one installation. Closest thing I know of is Rose::DBx::Garden::Catalyst, but even that seemed to require too much effort for a lazybones like me.
So about a year ago a chap called Andy Payne who was working at Dragonstaff produced the ListBuilder, a framework using Catalyst, DBIx::Class, Template::Toolkit, and the ExtJS Javascript library to churn out nice looking functionable CRUD interfaces to database tables. I spent a fun evening hacking with it 'til around 3 in the morning.
My eyes were opened to the real possibility, that the whole interface should be generated from information which DBIx::Class already knows; there's no need for us to be explaining things twice. I booked a few days off work and we now have CatalystX::ListFramework::Builder (LFB).
LFB needs only a few lines of configuration (database connection parameters), and then also needs you to have DBIx::Class schema classes available which describe your database, but those can be automagically generated by the excellent DBIx::Class::Schema::Loader module.
Out the other end of the sausage machine comes a Javascript-rich list-based, paged view of a database table, supporting search, delete, create and edit. LFB handles one-to-one and one-to-many relations, showing related data and allowing creation and linking of related rows when editing.
If you like the look of the module and want to know something, please do drop me a line; equally if there's a missing feature you desperately need we can probably arrange to have you buy some of my time. In the rest of this article I'll explain a little about how LFB works.
Your complete Catalyst application looks like this:
package ListFrameworkUser;
use base 'CatalystX::ListFramework::Builder';
__PACKAGE__->build_listframework('config.yml');
1;
You can take my word for it that the config really is trivial (an example is on the CPAN documentation page), with just database connection parameters and a URL path for the Javascript library. The base class used creates a Catalyst application on the fly in your application's namespace (ListFrameworkBuilder, here) which has all the Models, Views and Controllers needed to run LFB. It does this using a mixture of package-scoped eval(), %INC injection, and overriding a little of Catalyst's core (setup_components in particular, because of eval() vs. Module::Pluggable timing issues).
Once that is done, a begin() handler in Catalyst instructs a Model to introspect DBIx::Class for all the table, column, data type and relation information which it pops into the Catalyst application stash. This is used by Template::Toolkit templates to customize a truck-load of ExtJS Javascript which is sent to the browser as the main page, and which in turn draws the list-based table view.
From that, everything notches up a gear into Web 2.0 land, as the user interface conducts its business over JSON-based AJAX. As mentioned above, you can add, delete, edit and search for records in the paged list-based view, and there are a few more bells and whistles besides that.
What are the current limitations? Well, I have coded along the 80/20 principle so there are some missing features, and some parts are inefficient. For example only single column primary keys are supported, although perhaps this will be improved in the future. Also, I didn't want you to have to install much more besides LFB itself and the ExtJS 2.1 library, so a small number of static PNG icons are served from LFB rather than your web server. These are reasonable compromises given the aim of LFB which is to be a near-zero-conf quick-install web GUI for (probably) your legacy databases.
We're up to release 0.15 as I write this, and most of the recent work has been refactoring, and there is still a long way to go. Certainly, some of the logic used for creating related rows and so on in the database is sub-optimal (but it does support forward and reverse relations - belongs_to, might_have, has_one and has_many, in DBIx::Class parlance). Don't be too critical, but feedback and ideas (and hey, if you like it, some praise!) would be appreciated. I'm already working with a handful of early adopters to refine the UI.
Oh, and last but not least... you want to see a running demo of the system? Well as a reward for reading this whole article try this simple Albums application, at least until the use.perl.org effect brings down my friend Peter's little VM host

