DBIx-Class-Fixtures
view release on metacpan or search on metacpan
lib/DBIx/Class/Fixtures.pm view on Meta::CPAN
An array of relationships to be used in the cond clause.
{
"sets": [ {
"class": "Artist",
"quantiy": "all",
"cond": { "cds.position": { ">": 4 } },
"join": ["cds"]
} ]
}
Fetch all artists who have cds with position greater than 4.
=head2 fetch
Must be an array of hashes. Specifies which rels to also dump. For example:
{
"sets": [ {
"class": "Artist",
"ids": ["1", "3"],
"fetch": [ {
"rel": "cds",
"quantity": "3",
"cond": { "position": "2" }
} ]
} ]
}
Will cause the cds of artists 1 and 3 to be dumped where the cd position is 2.
Valid attributes are: 'rel', 'quantity', 'cond', 'has_many', 'might_have' and
'join'. rel is the name of the DBIx::Class rel to follow, the rest are the same
as in the set attributes. quantity is necessary for has_many relationships, but
not if using for belongs_to or might_have relationships.
=head2 has_many
Specifies whether to fetch has_many rels for this set. Must be a hash
containing keys fetch and quantity.
Set fetch to 1 if you want to fetch them, and quantity to either 'all' or an
integer.
Be careful here, dumping has_many rels can lead to a lot of data being dumped.
=head2 might_have
As with has_many but for might_have relationships. Quantity doesn't do anything
in this case.
This value will be inherited by all fetches in this set. This is not true for
the has_many attribute.
=head2 external
In some cases your database information might be keys to values in some sort of
external storage. The classic example is you are using L<DBIx::Class::InflateColumn::FS>
to store blob information on the filesystem. In this case you may wish the ability
to backup your external storage in the same way your database data. The L</external>
attribute lets you specify a handler for this type of issue. For example:
{
"sets": [{
"class": "Photo",
"quantity": "all",
"external": {
"file": {
"class": "File",
"args": {"path":"__ATTR(photo_dir)__"}
}
}
}]
}
This would use L<DBIx::Class::Fixtures::External::File> to read from a directory
where the path to a file is specified by the C<file> field of the C<Photo> source.
We use the uninflated value of the field so you need to completely handle backup
and restore. For the common case we provide L<DBIx::Class::Fixtures::External::File>
and you can create your own custom handlers by placing a '+' in the namespace:
"class": "+MyApp::Schema::SomeExternalStorage",
Although if possible I'd love to get patches to add some of the other common
types (I imagine storage in MogileFS, Redis, etc or even Amazon might be popular.)
See L<DBIx::Class::Fixtures::External::File> for the external handler interface.
=head1 RULE ATTRIBUTES
=head2 cond
Same as with L</SET ATTRIBUTES>
=head2 fetch
Same as with L</SET ATTRIBUTES>
=head2 join
Same as with L</SET ATTRIBUTES>
=head2 has_many
Same as with L</SET ATTRIBUTES>
=head2 might_have
Same as with L</SET ATTRIBUTES>
=head1 RULE SUBSTITUTIONS
You can provide the following substitution patterns for your rule values. An
example of this might be:
{
"sets": [{
"class": "Photo",
"quantity": "__ENV(NUMBER_PHOTOS_DUMPED)__",
}]
}
=head2 ENV
Provide a value from %ENV
=head2 ATTR
Provide a value from L</config_attrs>
=head2 catfile
Create the path to a file from a list
=head2 catdir
Create the path to a directory from a list
lib/DBIx/Class/Fixtures.pm view on Meta::CPAN
"".io->catdir(@args);
},
};
my $subsre = join( '|', keys %$subs );
$_ =~ s{__($subsre)(?:\((.+?)\))?__}{ $subs->{ $1 }->( $self, $2 ? split( /,/, $2 ) : () ) }eg;
return $_;
}
);
$v->visit( $set );
die 'no dir passed to dump_object' unless $params->{set_dir};
die 'no object passed to dump_object' unless $object;
my @inherited_attrs = @{$self->_inherited_attributes};
my @pk_vals = map {
$object->get_column($_)
} $object->primary_columns;
my $key = join("\0", @pk_vals);
my $src = $object->result_source;
my $exists = $self->dumped_objects->{$src->name}{$key}++;
# write dir and gen filename
my $source_dir = io->catdir($params->{set_dir}, $self->_name_for_source($src));
$source_dir->mkpath(0, 0777);
# Convert characters not allowed on windows
my $file = io->catfile("$source_dir",
join('-', map { s|[/\\:\*\|\?"<>]|_|g; $_; } @pk_vals) . '.fix'
);
# write file
unless ($exists) {
$self->msg('-- dumping ' . "$file", 2);
# get_columns will return virtual columns; we just want stored columns.
# columns_info keys seems to be the actual storage column names, so we'll
# use that.
my $col_info = $src->columns_info;
my @column_names = keys %$col_info;
my %columns = $object->get_columns;
my %ds; @ds{@column_names} = @columns{@column_names};
if($set->{external}) {
foreach my $field (keys %{$set->{external}}) {
my $key = $ds{$field};
my ($plus, $class) = ( $set->{external}->{$field}->{class}=~/^(\+)*(.+)$/);
my $args = $set->{external}->{$field}->{args};
$class = "DBIx::Class::Fixtures::External::$class" unless $plus;
eval "use $class";
$ds{external}->{$field} =
encode_base64( $class
->backup($key => $args),'');
}
}
# mess with dates if specified
if ($set->{datetime_relative}) {
my $formatter= eval {$object->result_source->schema->storage->datetime_parser};
unless (!$formatter) {
my $dt;
if ($set->{datetime_relative} eq 'today') {
$dt = DateTime->today;
} else {
$dt = $formatter->parse_datetime($set->{datetime_relative}) unless ($@);
}
while (my ($col, $value) = each %ds) {
my $col_info = $object->result_source->column_info($col);
next unless $value
&& $col_info->{_inflate_info}
&& (
(uc($col_info->{data_type}) eq 'DATETIME')
or (uc($col_info->{data_type}) eq 'DATE')
or (uc($col_info->{data_type}) eq 'TIME')
or (uc($col_info->{data_type}) eq 'TIMESTAMP')
or (uc($col_info->{data_type}) eq 'INTERVAL')
);
$ds{$col} = $object->get_inflated_column($col)->subtract_datetime($dt);
}
} else {
warn "datetime_relative not supported for this db driver at the moment";
}
}
# do the actual dumping
my $serialized = Dump(\%ds)->Out();
$file->print($serialized);
}
# don't bother looking at rels unless we are actually planning to dump at least one type
my ($might_have, $belongs_to, $has_many) = map {
$set->{$_}{fetch} || $set->{rules}{$src->source_name}{$_}{fetch}
} qw/might_have belongs_to has_many/;
return unless $might_have
|| $belongs_to
|| $has_many
|| $set->{fetch};
# dump rels of object
unless ($exists) {
foreach my $name (sort $src->relationships) {
my $info = $src->relationship_info($name);
my $r_source = $src->related_source($name);
# if belongs_to or might_have with might_have param set or has_many with
# has_many param set then
if (
( $info->{attrs}{accessor} eq 'single' &&
(!$info->{attrs}{join_type} || $might_have)
( run in 1.406 second using v1.01-cache-2.11-cpan-39bf76dae61 )