Our software has hundreds of database tables, dozens of which I have been tasked with making "searchable." And by "searchable" I mean a "global" search box that will do text matching against an index that is build from specific fields in each of these tables.
The task is complicated by the fact that each table doesn't have a clearly defined url-mapping scheme (so matching a row in a table is difficult to translate into a URL where the information can be accessed directly). I considered using a sprintf() type format specifier, but I think that will be too limited in the long run.
So the plan now is to have a generic "Searchable" class which can handle the easy-to-capture tables, such as ones that have a direct mapping from primary keys to urls. Then there will be other "Searchable" subclasses which are responsible for separating their content into "documents" which can then be added to the search index. The documents must contain a title, a url, a summary, and a body in a well-defined format ("document" in this case is not a file, but rather an in-memory
hash representation of this theoretical document). For example, if a table has a two-field primary key and three columns that we want searchable, the subclass will be responsible for turning that into a "document" which can be searched in a standard way.
What I want is an easy way to drop in a subclass which will represent another table and have the Indexer script catch that and call it's get_list() method automatically. This must run under strict and I'd like to not { no strict whatever; }, but I'm open to that if it's necessary. I've come up with something like:
#!/usr/bin/perl -w
use strict;
use SearchIndexer;
use Searchable::Generic;
use Searchable::Folder;
use Searchable::FamilyTree;
# ... whatever else ...
my @searchable = qw(Searchable::Generic Searchable::Folder Searchable:
+:FamilyTree);
my $indexer = new SearchIndexer();
foreach my $module (@searchable) {
$indexer->add($module::get_list());
}
$indexer->run();
So I'm wondering if anyone can come up with a better way to handle this. The above method will work, but obviously I have to add the entry to two places, in the "header" I have to add a "use module;" and then I also have to add it to the @searchable array. I want something that's more transparent, and yes, I'm open to restructuring this to make more sense if someone can think of a better way to do it.