TJPride has asked for the wisdom of the Perl Monks concerning the following question:
I do work for a company that does marketing for nearly 100 car dealerships around the US. A big part of this is importing and maintaining data for each dealership from a variety of older systems, and doing this requires a large number of config variables and even custom subs. Obviously, dumping these all in one huge .pm isn't a good option, and as far as I know, I can't "use" a path containing a variable (a keyword representing the dealer).
Or to put it another way, I have a folder called Config that contains x.pm, y.pm, z.pm, etc. where x, y, and z are dealer keywords. When I run a data import, I have a variable containing the dealer keyword, and I want to use just that one .pm, let's say x.pm. What's the best way to go about doing this? Up to now, I've been loading the file contents and using eval, but I'm wondering if there's a more elegant / more efficient way to do it.
Re: Best way to dynamically use a .pm?
by BrowserUk (Patriarch) on Nov 28, 2011 at 19:15 UTC
|
c:\test>type dealer\*.pm
dealer\x.pm
package config;
our $dealer = 'x';
dealer\y.pm
package config;
our $dealer = 'y';
dealer\z.pm
package config;
our $dealer = 'z';
c:\test>perl -E"my $p=shift; require qq[dealer/$p.pm]; say $config::de
+aler" x
x
c:\test>perl -E"my $p=shift; require qq[dealer/$p.pm]; say $config::de
+aler" y
y
c:\test>perl -E"my $p=shift; require qq[dealer/$p.pm]; say $config::de
+aler" z
z
With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] |
Re: Best way to dynamically use a .pm?
by CountZero (Bishop) on Nov 28, 2011 at 19:10 UTC
|
Check out UNIVERSAL::require. I think it will do exactly what you want.
CountZero A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James
| [reply] |
Re: Best way to dynamically use a .pm?
by JavaFan (Canon) on Nov 28, 2011 at 19:54 UTC
|
Why put configuration data in Perl modules? What's wrong with using a configuration file? At least that allows editing by "untrusted" people. | [reply] |
|
I'm the only one editing the system, so that doesn't really matter, at least for now. But can you give an example of how a config file is different from a Perl module? If it's a superior way to organize my code and as simple to use as require, I'm open-minded.
| [reply] |
|
| [reply] |
Re: Best way to dynamically use a .pm?
by patcat88 (Deacon) on Nov 28, 2011 at 19:51 UTC
|
Read use Module and require. PMs can put their subs in any package. PM names just look like packages, but they aren't, and a PM doesn't have to put subs in the package its named after (a good idea for unmaintainable code). PMs are simply text files given to the do EXPR function.
Note, you can write the require and use functions yourself in pure perl.
I think for your case 1 PM per data format, loaded using requires, or put a begin block read the data header and then do a require in the begin block, parse the file outside of the BEGIN block/normal runtime. | [reply] |
Re: Best way to dynamically use a .pm?
by choroba (Cardinal) on Nov 28, 2011 at 19:07 UTC
|
| [reply] |
Re: Best way to dynamically use a .pm?
by Tux (Canon) on Nov 29, 2011 at 14:42 UTC
|
Why put the data in .pm files? Can't it be controlled by data structures in some readable way, like JSON or YAML? Does it need to include code? If parameters in the config files can control program flow in the module, I'd say stick to config files and not dynamic modules. An alternative to JSON of YAML might be to look at any of the plethora of Config:: modules on CPAN.
Then there is the long forgotten support for files in the do keyword:
$ cat honda.pl
#!perl
print STDERR "Using Honda\n";
sub honda { print "Honda rulez\n"; }
1;
$ perl -wE'do "honda.pl";say 2;honda()'
Using Honda
2
Honda rulez
$
do does accept variables :)
Enjoy, Have FUN! H.Merijn
| [reply] [d/l] [select] |
|
Queries, templates, and the data interface between the two can vary widely between dealers, with no way to predict in advance. The best way to handle this is custom-modified subs, as far as I can tell. Essentially, the same .pm only in many different flavors. Maybe this isn't the best approach, but it seems to be working - I was only really concerned with efficiency, now that it'll have to be done for large numbers of transactions rather than just a few data imports.
| [reply] |
Re: Best way to dynamically use a .pm?
by cavac (Parson) on Nov 28, 2011 at 21:47 UTC
|
my $memd;
my $memd_loaded = 0;
# Decide which Memcached module we want to use
# First, we try the festest one, then the standard
# one and if everything fails we use our own
my $memdtype;
{
## no critic (BuiltinFunctions::ProhibitStringyEval)
if(eval('require Cache::Memcached::Fast')) {
print " Cache::Memcached::Fast available.\n";
$memdtype = "Cache::Memcached::Fast";
$memd = Cache::Memcached::Fast->new ({
servers => [ $self->{service} ],
namespace => $self->{namespace} . "::",
connect_timeout => 0,
});
$memd_loaded = 1;
$self->{mctype} = "fast";
} elsif(eval('require Cache::Memcached')) {
print " No Cache::Memcached::Fast ... falling back to C
+ache::Memcached\n";
$memdtype = "Cache::Memcached";
$memd = Cache::Memcached->new ({
servers => [ $self->{service} ],
namespace => $self->{namespace} . "::",
connect_timeout => 0,
});
$memd_loaded = 1;
$self->{mctype} = "slow";
} else {
print " No Cache::Memcached* available ... will try to
+use Maplat::Helpers::Cache::Memcached\n";
}
}
This just looks up which Memcached modules are available and tries to load one of those.
Don't use '#ff0000':
use Acme::AutoColor; my $redcolor = RED();
All colors subject to change without notice.
| [reply] [d/l] |
Re: Best way to dynamically use a .pm?
by TJPride (Pilgrim) on Nov 28, 2011 at 19:31 UTC
|
"use if" requires a statement for every keyword, which gets a bit messy with 100+ keywords (possibly hundreds in the future). I suppose I could use a .pm which then has all the statements, but that seems an overly complicated way to do it.
Similarly, I don't want to mess with extra Perl modules if it isn't absolutely necessary.
require "$x.pm", however, does seems to work, and in a very simple way. | [reply] |
Re: Best way to dynamically use a .pm?
by Anonymous Monk on Nov 29, 2011 at 03:35 UTC
|
Simple Module Tutorial, use, require, find, Module::Load, Module::List, Plugins, Module::Pluggable, Module::Load, ToolSet, relative, Module::Pluggable, Module::Find,
code that runs (and works) on both Linux and Win32, constants wont optimize, How do you say, in Perl...., On kind of dynamic loading
- Perl documentation
- if
- Module::Load - runtime require of both modules and files
- Module::Load::Conditional - Looking up module information / loading at runtime
- Module::Loaded - mark modules as loaded or unloaded
- Module::Pluggable - automatically give your module the ability to have plugins
- Module::Pluggable::Object - automat
| [reply] |
Re: Best way to dynamically use a .pm?
by sundialsvc4 (Abbot) on Nov 29, 2011 at 03:15 UTC
|
The admonition to use UNIVERSAL is a very good one, because (having actually overlooked its existence until this moment ...) the logic for constructing a successful "require" is very messy indeed.
Now, if you will pardon me while I go and fix a bunch of very smelly old code.
| [reply] |
Re: Best way to dynamically use a .pm?
by Tux (Canon) on Nov 29, 2011 at 14:36 UTC
|
Why put the data in .pm files? Can't it be controlled by data structures in some readable way, like JSON, YAML, or CSV? Does it need to include code? If parameters in the config files can control program flow in the module, I'd say stick to config files and not dynamic modules. An alternative to JSON, YAML, or CSV might be to look at any of the plethora of Config:: modules on CPAN.
update: that was a browser hick-up. Sorry. Just view the other answer.
Enjoy, Have FUN! H.Merijn
| [reply] |
|
|