File Coverage

blib/lib/Tie/Redis/Attribute.pm
Criterion Covered Total %
statement 30 67 44.7
branch 1 24 4.1
condition 0 16 0.0
subroutine 11 14 78.5
pod 1 1 100.0
total 43 122 35.2


line stmt bran cond sub pod time code
1             package Tie::Redis::Attribute;
2             BEGIN {
3 2     2   268937 $Tie::Redis::Attribute::VERSION = '0.22_1';
4             }
5             # ABSTRACT: Variable attribute based interface to Tie::Redis
6              
7 2     2   40 use 5.010001; # >= 5.10.1
  2         5  
8 2     2   11 use strict;
  2         3  
  2         53  
9 2     2   9 use warnings;
  2         2  
  2         63  
10              
11 2     2   1283 use Attribute::Handlers;
  2         8840  
  2         12  
12 2     2   931 use Tie::Redis;
  2         6  
  2         117  
13 2     2   984 use PadWalker qw(var_name);
  2         1260  
  2         147  
14              
15 2     2   11 no warnings 'redefine';
  2         2  
  2         431  
16              
17             sub import {
18 2     2   83 my($class) = @_;
19 2         4 my $pkg = caller;
20 2 50   2   9 eval qq{
  2     0   2  
  2         13  
  0         0  
  0         0  
  2         143  
21             sub ${pkg}::Redis :ATTR(VAR) {
22             unshift \@_, \$class;
23             goto &_do_tie;
24             }
25             1
26             } or die;
27             }
28              
29             sub _do_tie {
30 0     0     my($class, $ref, $data) = @_[0, 3, 5];
31 0 0         return if tied $ref; # Already applied
32              
33 0 0 0       if($data && !ref $data) {
34             # Attribute::Handlers couldn't make into perl, warn rather than do
35             # something surprising.
36 0           require Carp;
37 0           Carp::croak "Invalid attribute";
38             }
39              
40 0           my $type = ref $ref;
41 0 0         my %args = ref $data ? @$data : ();
42              
43 0 0         if(!exists $args{key}) {
44             my $sigil = {
45             ARRAY => '@',
46             HASH => '%'
47 0           }->{$type};
48              
49             # Find where we were actually called from, ignoring attributes and
50             # Attribute::Handlers.
51 0           my $c = 1;
52 0           $c++ while((caller $c)[3] =~ /^(?:attributes|Attribute::Handlers)::/);
53              
54             # The first part of the key is either the name of the subroutine if this is
55             # within sub scope else the package name.
56 0           my $pkg = (caller $c+1)[0];
57 0   0       my $sub = (caller $c+1)[3] || $pkg;
58              
59             # Now we want a unique name for it
60 0           my $name = var_name($c, $ref);
61              
62 0 0         if(!$name) {
63             # Maybe package variable?
64 2     2   9 no strict 'refs';
  2         2  
  2         628  
65 0           for my $glob(values %{"${pkg}::"}) {
  0            
66 0 0         next unless ref \$glob eq 'GLOB';
67 0 0 0       if(*$glob{$type} && *$glob{$type} == $ref) {
68 0           $name = $sigil . ($glob =~ /::([^:]+)$/)[0];
69             }
70             }
71             }
72              
73 0 0         if(!$name) {
74 0           require Carp;
75 0           local $Carp::CarpLevel = $c;
76 0           Carp::croak "Can't automatically work out a name";
77             }
78              
79 0 0         if($pkg eq 'main') {
80             # DWIM..., hopefully not *too* magical
81 0           ($pkg) = $0 =~ m{(?:^|/)([^/]+)$};
82 0           $sub =~ s/^main(::|$)/${pkg}$1/;
83             }
84 0           $args{key} = "autoattr:${sub}::${name}";
85             }
86              
87 0 0         if($type eq 'HASH') {
    0          
88 0           tie %$ref, "Tie::Redis::" . ucfirst lc $type,
89             redis => $class->server(%args), %args;
90             } elsif($type eq 'ARRAY') {
91 0           tie @$ref, "Tie::Redis::" . ucfirst lc $type,
92             redis => $class->server(%args), %args;
93             } else {
94 0           die "Only hashes and arrays are supported";
95             }
96             }
97              
98             sub server {
99 0     0 1   my($class, %args) = @_;
100 0           state %server;
101              
102 0   0       $server{($args{host}||"") . ":" . ($args{port}||"")}
      0        
      0        
103             ||= Tie::Redis->new(%args);
104             }
105              
106             1;
107              
108              
109              
110             =pod
111              
112             =head1 NAME
113              
114             Tie::Redis::Attribute - Variable attribute based interface to Tie::Redis
115              
116             =head1 VERSION
117              
118             version 0.22_1
119              
120             =head1 SYNOPSIS
121              
122             use Tie::Redis::Attribute;
123              
124             my %hash : Redis; # %hash now magically resides in a redis instance
125              
126             =head1 DESCRIPTION
127              
128             This is an B module that implements attribute based tying for
129             Redis.
130              
131             Currently tying of arrays or hashes is supported.
132              
133             =head1 OPTIONS
134              
135             Options may be specified using perl list syntax within the C
136             attribute.
137              
138             However note that L cannot use lexical variables, so C
139             Redis(host => $host)> will unfortunately not work if C<$host> is lexical.
140              
141             =over 4
142              
143             =item * key
144              
145             The key to use, if this isn't provided a key is invented based on the package
146             name and variable name. This means for some simple purposes you may not need to
147             specify a key.
148              
149             For example:
150              
151             our @queue : Redis(key => "my-queue");
152              
153             =back
154              
155             Other options are as per L's constructor (prefix) and
156             L (host, port, encoding).
157              
158             =head1 METHODS
159              
160             =head2 server
161              
162             You may subclass this and define a C method that returns an instance of
163             L. Due to the I nature of attributes it is recommended to
164             B define an C method in your subclass other than the one provided
165             by this class.
166              
167             =head1 SEE ALSO
168              
169             L, L, L.
170              
171             =head1 AUTHOR
172              
173             David Leadbeater
174              
175             =head1 COPYRIGHT AND LICENSE
176              
177             This software is copyright (c) 2011 by David Leadbeater.
178              
179             This is free software; you can redistribute it and/or modify it under
180             the terms of the Beerware license.
181              
182             =cut
183              
184              
185             __END__