File Coverage

blib/lib/Rose/Planter/Soil.pm
Criterion Covered Total %
statement 42 54 77.7
branch 12 26 46.1
condition 3 8 37.5
subroutine 6 7 85.7
pod 2 2 100.0
total 65 97 67.0


line stmt bran cond sub pod time code
1             package Rose::Planter::Soil;
2              
3             =head1 NAME
4              
5             Rose::Planter::Soil -- default base object class for classes created by Rose::Planter.
6              
7             =head1 DESCRIPTION
8              
9             This provides a few extra handy functions and
10             defaults for manipulating Rose classes.
11              
12             =head1 METHODS
13              
14             =cut
15              
16 2     2   6529 use strict;
  2         5  
  2         51  
17 2     2   11 use warnings;
  2         20  
  2         57  
18              
19 2     2   10 use Log::Log4perl qw/:easy/;
  2         2  
  2         14  
20 2     2   1418 use base 'Rose::DB::Object';
  2         3  
  2         168  
21 2     2   11 use Rose::DB::Object::Helpers qw/:all/;
  2         3  
  2         37  
22              
23             =head2 as_hash
24              
25             Like Rose::DB::Object::Helper::as_tree but with a few differences :
26              
27             - parent keys in a child table are excluded.
28              
29             - datetimes are returned in ISO 8601 format.
30              
31             - the parameter skip_re can be given to skip columns matching a regex.
32              
33             - only one-to-one and one-to-many relationships are traversed
34              
35             =cut
36              
37             sub as_hash {
38 3     3 1 17586 my $self = shift;
39 3         53 my %args = @_;
40 3         6 my $skip_re = $args{skip_re};
41 3         5 my $parent = $args{_parent};
42 3         5 my %parent_columns;
43              
44 3 100       12 if ($parent) {
45 2         10 %parent_columns = reverse $parent->column_map;
46             }
47              
48 3         23 my %h; # to be returned.
49              
50 3         12 for my $col ( $self->meta->columns ) {
51 8 100       100 next if $parent_columns{$col->name};
52 6         60 my $accessor = $col->accessor_method_name;
53 6         193 my $value = scalar( $self->$accessor );
54 6 50       41 if (ref $value eq 'DateTime') {
55             # timezone may be a DateTime::TimeZone::OffsetOnly
56             # whose name is e.g. -0400. It needs to be -04:00 for iso 8601.
57 0         0 my $offset = $value->time_zone->name;
58 0         0 $value = $value->iso8601;
59 0 0       0 if ($offset =~ /\d{4}/ ) {
    0          
60 0         0 $offset=~ s/00$/:00/;
61 0         0 $value .= $offset;
62             } elsif ($offset =~ /^UTC|floating/) {
63             # ok
64             } else {
65             # Could this happen with an explicitly set timezone?
66 0         0 WARN "unrecognized timezone name : $offset";
67             }
68             }
69 6 50 33     18 next if $skip_re && $accessor =~ /$skip_re/;
70 6         17 $h{$accessor} = $value;
71             }
72              
73 3         12 for my $rel ($self->meta->relationships) {
74 3 100       80 next unless $rel->object_has_related_objects($self); # undocumented API call
75 1         51 my $name = $rel->name;
76 1 50       9 die "cannot recurse" unless $self->can($name);
77 1 50       6 if ($rel->type eq 'one to one') {
    50          
78 0         0 $h{$name} = $self->$name->as_hash( _parent => $rel);
79             } elsif ($rel->type eq 'one to many') {
80 1         16 my @children = $self->$name;
81 1         14 for my $child (@children) {
82 2 50       15 die "cannot dump $name" unless $child->can('as_hash');
83 2   100     12 $h{$name} ||= [];
84 2         2 push @{ $h{$name} }, $child->as_hash( _parent => $rel);
  2         13  
85             }
86             } else {
87             # warn "relationship type ".$rel->type." not implemented in as_hash";
88             # silently skip many-to-one relationships
89             }
90             }
91              
92 3         59 return \%h;
93             }
94              
95             =head2 nested_tables
96              
97             Get or set a list of "nested table" associated with this
98             class. These are tables which are always retrieved alongside
99             this one.
100              
101             =cut
102              
103             our %NestedMap;
104             sub nested_tables {
105             # The Right way to do this is probably to provide our own base meta class, too.
106 0     0 1   my $self = shift;
107 0   0       my $class = ref $self || $self;
108 0 0         return $NestedMap{$class} unless @_ > 0;
109 0 0         $NestedMap{$class} = ref($_[0]) ? shift : [ @_ ];
110 0           return $NestedMap{$class};
111             }
112              
113             1;
114