File Coverage

blib/lib/Data/Faker.pm
Criterion Covered Total %
statement 60 63 95.2
branch 10 14 71.4
condition 2 3 66.6
subroutine 11 12 91.6
pod 3 3 100.0
total 86 95 90.5


line stmt bran cond sub pod time code
1             package Data::Faker;
2 7     7   218935 use vars qw($VERSION); $VERSION = '0.10';
  7         16  
  7         1234  
3              
4             =head1 NAME
5              
6             Data::Faker - Perl extension for generating fake data
7              
8             =head1 SYNOPSIS
9              
10             use Data::Faker;
11              
12             my $faker = Data::Faker->new();
13              
14             print "Name: ".$faker->name."\n";
15             print "Company: ".$faker->company."\n";
16             print "Address: ".$faker->street_address."\n";
17             print " ".$faker->city.", ".$faker->us_state_abbr." ".$faker->us_zip_code."\n";
18              
19             =head1 DESCRIPTION
20              
21             This module creates fake (but reasonable) data that can be used for things
22             such as filling databases with fake information during development of
23             database related applications.
24              
25             =cut
26              
27 7     7   40 use strict;
  7         13  
  7         318  
28 7     7   37 use warnings;
  7         15  
  7         329  
29 7     7   40 use File::Spec ();
  7         12  
  7         180  
30 7     7   33 use Carp 'croak';
  7         15  
  7         3550  
31             my %plugins;
32             my @always_import;
33              
34             =head1 OBJECT METHODS
35              
36             =over 4
37              
38             =item new()
39              
40             Object constructor. As a shortcut, you can pass names of plugin modules to
41             load to new(), although this does not actually restrict the functions available
42             to the object, it just causes those plugins to be loaded if they haven't been
43             loaded already. All Data::Faker objects in one interpreter share the plugin
44             data, so that multiple objects don't multiply the memory requirements.
45              
46             =cut
47              
48             sub new {
49 14     14 1 31301 my $pack = shift;
50 14         36 my $self = {};
51 14         37 bless($self,$pack);
52 14         49 my @import = (@_,@always_import);
53 14 100       57 unless(@import) { push(@import,'*'); }
  2         6  
54 14         37 foreach my $import (@import) {
55 14         41 foreach(@INC) {
56 154         9760 for(glob(File::Spec->catfile($_, qw/Data Faker/,"$import.pm"))) {
57 168 100 66     43131 require $_ if -f $_ && -r _;
58             }
59             }
60             }
61 14         95 return $self;
62             }
63              
64 27     27   126 sub import { my $self = shift; push(@always_import,@_); }
  27         39018  
65              
66             =item methods();
67              
68             Return a list of the methods that have been provided by all of the loaded
69             plugins.
70              
71             =cut
72              
73 7     7 1 166 sub methods { return keys %Data::Faker::plugins; }
74              
75             =item register_plugin();
76              
77             Plugin modules call register_plugin() to provide data methods. See any of
78             the included plugin modules for examples.
79              
80             =cut
81              
82             sub register_plugin {
83 238     238 1 396 my $self = shift;
84 238         442 my @functions = @_;
85              
86 238         549 push(@{$Data::Faker::plugins{shift()}}, shift()) while @_;
  238         1332  
87             }
88              
89 7     7   61 use vars qw($AUTOLOAD);
  7         13  
  7         4761  
90             sub AUTOLOAD {
91 247     247   57817 my $self = shift;
92 247         344 my $al = $AUTOLOAD;
93 247         1311 $al =~ s/.*:://;
94 247 50       459 my @data = @{$Data::Faker::plugins{$al} || []};
  247         1237  
95 247 50       540 croak "No data found for method '$al'" unless @data;
96              
97 247         932 my $data = $data[rand(@data)];
98              
99 247         272 my $result;
100 247 50       897 if(! ref($data)) {
    100          
    50          
101 0         0 $result = $data;
102             } elsif(ref($data) eq 'ARRAY') {
103 171         229 $result = $data->[rand(@{$data})];
  171         601  
104             } elsif(ref($data) eq 'CODE') {
105 76         250 $result = $data->($self);
106             } else {
107 0         0 croak "Don't know what to do with result of type '".ref($data)."'";
108             }
109 247         701 $result =~ s/\0//g;
110              
111             # replace any tokens that need expansion
112 247         320 $result =~ s/\\\$/\0/g;
113 247         698 while($result =~ /\$(\w+)/) {
114 87         197 my $what = $1;
115 87         566 my $r = $self->$what();
116 87         17380 $result =~ s/\$$what/$r/;
117             }
118 247         295 $result =~ s/\0/\$/g;
119              
120             # replace any number needing expansion
121 247         907 $result =~ s/\\#/\0/g;
122 247         379 $result =~ s/#/int(rand(10))/ge;
  59         127  
123 247         291 $result =~ s/\0/#/g;
124              
125 247         2880 return $result;
126             }
127              
128 0     0     sub DESTROY {}
129              
130             =back
131              
132             =head1 LOADING PLUGINS
133              
134             You can specify which plugins to load by including just the base part of their
135             name as an argument when loading the module with 'use'. For example if you
136             only wanted to use data from the Data::Faker::Name module, you would load
137             Data::Faker like this:
138              
139             use Data::Faker qw(Name);
140              
141             By default any modules matching Data::Faker::* in any directory in @INC
142             will be loaded. You can also pass plugin names when calling the new() method,
143             and they will be loaded if not already in memory. See L.
144              
145             =head1 WRITING PLUGINS
146              
147             Writing a plugin to provide new kinds of data is easy, all you have to do is
148             create a module named Data::Faker::SomeModuleName that inherits from
149             Data::Faker.
150              
151             To provide data, the plugin merely needs to call the register_plugin function
152             with one or more pairs of function name and function data, like this:
153              
154             #!/usr/bin/perl -w
155             use strict;
156             use warnings;
157             use Data::Faker;
158              
159             my $faker = Data::Faker->new();
160             print "My fake data is ".$faker->some_data_function."\n";
161              
162             package Data::Faker::SomeData;
163             use base 'Data::Faker';
164              
165             __PACKAGE__->register_plugin(
166             some_data_function => [qw(foo bar baz gazonk)],
167             another_data_item => sub { return '$some_data_function' },
168             );
169              
170             The first argument is the method that will be made available to your object,
171             the second is a data source. If the data source is not a reference, it will
172             simply be returned as the data, if it is a reference to an array, a random
173             element from the array will be returned, and if it is a subroutine reference,
174             the subroutine will be run and the results will be returned. The data that
175             your data source provides is checked for two things, tokens (that look like
176             perl variables, starting with a $), and numeric indicators (#). Any tokens
177             found will be replaced with their values, and any numeric indicators will be
178             replaced with random numbers. You can include a literal $ or # by prefacing
179             it with a backslash. If you load more than one module that defines the same
180             function, it has an additive effect, when the function is called one of the
181             data sources provided will be selected at random and then it will be called
182             to get a piece of data.
183              
184             Some data source examples:
185              
186             __PACKAGE__->register_plugin(
187             age => ['#','##'],
188             monetary_amount => ['\$####.##','\$###.##', '\$##.##', '\$#.##'],
189             adult_age => sub { int(rand(70)+18) },
190             );
191              
192             If your data source is a code reference, it will receive the calling object
193             as an argument so you can build data out of other data if you need to. See
194             L for some examples of this.
195              
196             =head1 BUGS AND KNOWN ISSUES
197              
198             There is no way to selectively remove data sources from a plugin that was
199             loaded, even if you didn't load it.
200              
201             =head1 SEE ALSO
202              
203             Text::Lorem
204              
205             =head1 AUTHOR
206              
207             Jason Kohles, Eemail@jasonkohles.comE
208              
209             =head1 COPYRIGHT AND LICENSE
210              
211             Copyright 2004-2005 by Jason Kohles
212              
213             This library is free software; you can redistribute it and/or modify
214             it under the same terms as Perl itself.
215              
216             =cut
217              
218             1;