ACME-QuoteDB
view release on metacpan or search on metacpan
lib/ACME/QuoteDB.pm view on Meta::CPAN
}
sub _get_quote_ref_from_all {
my (@results) = @_;
#my ($results) = @_;
my $quotes_ref = [];
#foreach my $q_obj ( @{$results} ){
foreach my $q_obj ( @results ){
next unless $q_obj->quote;
my $rec = Attr->retrieve($q_obj->attr_id);
my $attr_name = $rec->name || q{};
push @{ $quotes_ref }, $q_obj->quote . "\n-- $attr_name";
}
return $quotes_ref;
}
sub _args_are_valid {
my ( $arg_ref, $accepted ) = @_;
my $arg_ok = 0;
foreach my $arg ( %{$arg_ref} ) {
if ( scalar grep { $arg =~ $_ } @{$accepted} ) {
$arg_ok = 1;
}
}
if (!$arg_ok) {croak 'unsupported argument option passed'}
}
sub add_quote {
my ( $self, $arg_ref ) = @_;
_args_are_valid($arg_ref, [qw/Quote AttrName Source Rating Category/]);
my $load_db = ACME::QuoteDB::LoadDB->new({
#verbose => 1,
});
$load_db->set_record(quote => $arg_ref->{Quote});
$load_db->set_record(name => $arg_ref->{AttrName});
$load_db->set_record(source => $arg_ref->{Source});
$load_db->set_record(catg => $arg_ref->{Category});
$load_db->set_record(rating => $arg_ref->{Rating});
if ($load_db->get_record('quote') and $load_db->get_record('name')) {
return $load_db->write_record;
}
else {
croak 'quote and attribution name are mandatory parameters';
}
return;
}
# XXX lame, can only get an id from exact quote
sub get_quote_id {
my ( $self, $arg_ref ) = @_;
if (not $arg_ref) {croak 'Quote required'}
_args_are_valid($arg_ref, [qw/Quote/]);
my $ids = _get_quote_id_from_quote($arg_ref->{'Quote'});
return join "\n", sort @{$ids};
}
sub update_quote {
my ( $self, $arg_ref ) = @_;
if (not $arg_ref) {croak 'QuoteId and Quote required'}
_args_are_valid($arg_ref, [qw/Quote QuoteId Source
Category Rating AttrName/]);
my $q = Quote->retrieve($arg_ref->{'QuoteId'});
my $atr = Attr->retrieve($q->attr_id);
# XXX need to support multi categories
#my $ctg = Catg->retrieve($q->catg_id);
my $qc = QuoteCatg->retrieve($q->quot_id);
my $ctg = Catg->retrieve($qc->catg_id);
$q->quote($arg_ref->{'Quote'});
if ($arg_ref->{'Source'}){$q->source($arg_ref->{'Source'})}
if ($arg_ref->{'Rating'}){$q->rating($arg_ref->{'Rating'})};
if ($arg_ref->{'AttrName'}){$atr->name($arg_ref->{'AttrName'})};
# XXX need to support multi categories
if ($arg_ref->{'Category'}){
$ctg->catg($arg_ref->{'Category'})
}
return ($q->update && $atr->update && $ctg->update);
}
sub delete_quote {
my ( $self, $arg_ref ) = @_;
if (not $arg_ref) {croak 'QuoteId required'}
_args_are_valid($arg_ref, [qw/QuoteId/]);
my $q = Quote->retrieve($arg_ref->{'QuoteId'});
#$q->quote($arg_ref->{'QuoteId'});
return $q->delete;
}
sub get_quote {
my ( $self, $arg_ref ) = @_;
# default use case, return random quote from all
if (not $arg_ref) {
return _get_one_rand_quote_from_all;
}
_args_are_valid($arg_ref, [qw/Rating AttrName Source Category/]);
my ($lower, $upper) = (q{}, q{});
if ($arg_ref->{'Rating'}) {
($lower, $upper) = _get_rating_params($arg_ref->{'Rating'});
}
my $attr_name = q{};
if ( $arg_ref->{'AttrName'} ) {
$attr_name = _rm_beg_end_space($arg_ref->{'AttrName'});
}
my $source = q{};
if ( $arg_ref->{'Source'} ) {
$source = _rm_beg_end_space($arg_ref->{'Source'});
}
my $catg; # will become scalar or array ref
if ( $arg_ref->{'Category'} ) {
$catg = _rm_beg_end_space($arg_ref->{'Category'});
}
# use case for attribution, return random quote
my $quotes_ref =
_get_rand_quote_for_attribution($attr_name, $lower,
$upper, q{}, q{}, $source, $catg);
# one random from specified pool
return $quotes_ref->[rand scalar @{$quotes_ref}];
}
# XXX isn't there a method in DBI for this, bind something,...
# TODO follow up
sub _make_correct_num_of_sql_placeholders {
my ($ids) = @_;
# XXX a hack to make a list of '?' placeholders
my @qms = ();
for (1..scalar @{$ids}) {
push @qms, '?';
}
lib/ACME/QuoteDB.pm view on Meta::CPAN
=end comment
=head1 DIAGNOSTICS
An error such as:
C<DBD::SQLite::db prepare_cached failed: no such table: ,...>
probably means that you do not have a database created in the correct format.
basically, you need to create the database, usually, on a first run
you need to add the flag (to the loader):
create_db => 1, # first run, create the db
appending to an existing database is the default behaviour
see L<ACME::QuoteDB::LoadDB/create_db_tables>
=head1 CONFIGURATION AND ENVIRONMENT
if you are running perl > 5.8.5 and have access to
install cpan modules, you should have no problem installing this module
(utf-8 support in DBD::SQLite not avaible until 5.8 - we don't support 'non
utf-8 mode)
=over 1
=item * By default, the quotes database used by this module installs in the
system path, 'lib', (See L<Module::Build/"INSTALL PATHS">)
as world writable - i.e. 0666 (and probably owned by root)
If you don't like this, you can modify Build.PL to not chmod the file and it
will install as 444/readonly, you can also set a chown in there for whoever
you want to have RW access to the quotes db.
Alternativly, one can specify a location to a quotes database (file) to use.
(Since the local mode is sqlite3, the file doesn't even need to exist, just
needs read/write access to the path on the filesystem)
Set the environmental variable:
$ENV{ACME_QUOTEDB_PATH} (untested on windows)
(this has to be set before trying a database load and also (everytime before
using this module, obviouly)
Something such as:
BEGIN {
# give alternate path to the DB
# doesn't need to exist, will create
$ENV{ACME_QUOTEDB_PATH} = '/home/me/my_stuff/my_quote_db'
}
* (NOTE: be sure this (BEGIN) exists *before* the 'use ACME::QuoteDB' lines)
The default is to use sqlite3.
In order to connect to a mysql database, several environmental variables
are required.
BEGIN {
# have to set this to use remote database
$ENV{ACME_QUOTEDB_REMOTE} = 'mysql';
$ENV{ACME_QUOTEDB_DB} = 'acme_quotedb';
$ENV{ACME_QUOTEDB_HOST} = 'localhost';
$ENV{ACME_QUOTEDB_USER} = 'acme_user';
$ENV{ACME_QUOTEDB_PASS} = 'acme';
}
Set the above in a begin block.
The database connection is transparent.
Module usage wise, all operations are the same but now
you will be writing to the remote mysql database specified.
(The user will need read/write permissions to the db/tables)
(mysql admin duties are beyond the scope of this module)
The only supported databases at this time are sqlite and mysql.
It is trivial to add support for others
=back
=head1 DEPENDENCIES
L<Carp>
L<Data::Dumper>
L<criticism> (pragma - enforce Perl::Critic if installed)
L<version>(pragma - version numbers)
L<aliased>
L<Test::More>
L<DBD::SQLite>
L<DBI>
L<Class::DBI>
L<File::Basename>
L<Readonly>
L<Cwd>
L<Module::Build>
=head1 INCOMPATIBILITIES
none known of
=head1 SEE ALSO
man fortune (unix/linux)
L<Fortune>
L<fortune>
L<Acme::RandomQuote::Base>
L<WWW::LimerickDB>
=begin comment
C<Fortune> http://search.cpan.org/~gward/Fortune-0.2/Fortune.pm
C<fortune> http://search.cpan.org/~cwest/ppt-0.14/bin/fortune
C<Acme::RandomQuote::Base> http://search.cpan.org/~mangaru/Acme-RandomQuote-Base-0.01/lib/Acme/RandomQuote/Base.pm
C<WWW::LimerickDB> http://search.cpan.org/~zoffix/WWW-LimerickDB-0.0305/lib/WWW/LimerickDB.pm
=end comment
=head1 AUTHOR
David Wright, C<< <david_v_wright at yahoo.com> >>
=head1 TODO
=over 2
=item 1 if the database cannot be found, no error is printed!!!
or if you have no write access to it!
"you'll just get 'no attribute can be found,,...", which is cryptic to say
the least!
=item 1 add a dump backup to csv
a backup mechanism for your db to a regular text csv file.
=item 1 clean up tests 'skip if module X' not installed
(one of sqlite3 or mysql is required). currently dies if DBD::SQLite not
installed
=item 1 support multiple categories from LoadDB
how to load multipul categories from a csv file?
(try to avoid somthing ugly in our csv file format). or maybe don't support
this.
=item 1 (possibly) support long/short quotes output (see 'man fortune')
=back
=head1 BUGS AND LIMITATIONS
The CRUD stuff is weak for sure.
(i.e. add_quote, update_quote, delete_quote, get_quote_id)
For example, currently you can only get the quote id from the exact quote
In the future, I may just expose the DBI::Class object directly
to those that need/want it.
=begin comment
get_quotes_contain uses %search% to do it's pattern mattching, so that will
miss some obvious searches, which it should find.
i.e.
'Bill' will not find 'Bill' , beginning and endings of words will be off.
XXX - look at search_like, instead of what you are doing now
=end comment
currently, I am not encapsulating the record data structure used
by LoadDB->write. (i.e. it's a typical perl5 ojbect, the blessed hash)
I will for sure be encapsulating all data in a future version.
(so, don't have code that does $self->{record}->{name} = 'value', or you won't
be happy down the road). Instead use $self->get_record('name') (getter) or
$self->set_record(name => 'my attrib') (setter)
When we are using a SQLite database backend ('regular' local usage), we
should probably be using, ORLite instead of Class::DBI
(although we have not seen any issues yet).
Please report any bugs or feature requests to C<bug-acme-quotedb at rt.cpan.org>, or through
the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=ACME-QuoteDB>.
I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
=head1 SUPPORT
You can find documentation for this module with the perldoc command.
perldoc ACME::QuoteDB
( run in 1.881 second using v1.01-cache-2.11-cpan-39bf76dae61 )