Commit | Line | Data |
e59193fb |
1 | |
e59193fb |
2 | package MooseX::Storage; |
ec9c1923 |
3 | use Moose qw(confess); |
e59193fb |
4 | |
eebcb6dc |
5 | use MooseX::Storage::Meta::Attribute::DoNotSerialize; |
6 | |
f4ffa4ef |
7 | our $VERSION = '0.17'; |
69b45b7d |
8 | our $AUTHORITY = 'cpan:STEVAN'; |
7b428d1f |
9 | |
e59193fb |
10 | sub import { |
11 | my $pkg = caller(); |
ec9c1923 |
12 | |
13 | return if $pkg eq 'main'; |
14 | |
15 | ($pkg->can('meta')) |
16 | || confess "This package can only be used in Moose based classes"; |
17 | |
f9143059 |
18 | $pkg->meta->add_method('Storage' => __PACKAGE__->meta->find_method_by_name('_injected_storage_role_generator')); |
19 | } |
20 | |
21 | sub _injected_storage_role_generator { |
22 | my %params = @_; |
4d1850a6 |
23 | |
f9143059 |
24 | if (exists $params{'base'}) { |
25 | $params{'base'} = ('Base::' . $params{'base'}); |
26 | } |
27 | else { |
28 | $params{'base'} = 'Basic'; |
29 | } |
ec9c1923 |
30 | |
f9143059 |
31 | my @roles = ( |
32 | ('MooseX::Storage::' . $params{'base'}), |
33 | ); |
4d1850a6 |
34 | |
f9143059 |
35 | # NOTE: |
36 | # you don't have to have a format |
37 | # role, this just means you dont |
38 | # get anything other than pack/unpack |
39 | push @roles => 'MooseX::Storage::Format::' . $params{'format'} |
40 | if exists $params{'format'}; |
ec9c1923 |
41 | |
f9143059 |
42 | # NOTE: |
43 | # many IO roles don't make sense unless |
44 | # you have also have a format role chosen |
45 | # too, the exception being StorableFile |
46 | if (exists $params{'io'}) { |
ec9c1923 |
47 | # NOTE: |
f9143059 |
48 | # we dont need this code anymore, cause |
49 | # the role composition will catch it for |
50 | # us. This allows the StorableFile to work |
51 | #(exists $params{'format'}) |
52 | # || confess "You must specify a format role in order to use an IO role"; |
53 | push @roles => 'MooseX::Storage::IO::' . $params{'io'}; |
54 | } |
4d1850a6 |
55 | |
f9143059 |
56 | Class::MOP::load_class($_) |
57 | || die "Could not load role (" . $_ . ")" |
58 | foreach @roles; |
ec9c1923 |
59 | |
f9143059 |
60 | return @roles; |
e59193fb |
61 | } |
62 | |
ec9c1923 |
63 | 1; |
e59193fb |
64 | |
ec9c1923 |
65 | __END__ |
e59193fb |
66 | |
ec9c1923 |
67 | =pod |
e59193fb |
68 | |
ec9c1923 |
69 | =head1 NAME |
e9739624 |
70 | |
b430caa3 |
71 | MooseX::Storage - An serialization framework for Moose classes |
e59193fb |
72 | |
ec9c1923 |
73 | =head1 SYNOPSIS |
e9739624 |
74 | |
1390c23d |
75 | package Point; |
76 | use Moose; |
77 | use MooseX::Storage; |
78 | |
c1830046 |
79 | our $VERSION = '0.01'; |
80 | |
1390c23d |
81 | with Storage('format' => 'JSON', 'io' => 'File'); |
82 | |
83 | has 'x' => (is => 'rw', isa => 'Int'); |
84 | has 'y' => (is => 'rw', isa => 'Int'); |
85 | |
86 | 1; |
87 | |
88 | my $p = Point->new(x => 10, y => 10); |
89 | |
90 | ## methods to pack/unpack an |
91 | ## object in perl data structures |
92 | |
93 | # pack the class into a hash |
c1830046 |
94 | $p->pack(); # { __CLASS__ => 'Point-0.01', x => 10, y => 10 } |
1390c23d |
95 | |
96 | # unpack the hash into a class |
c1830046 |
97 | my $p2 = Point->unpack({ __CLASS__ => 'Point-0.01', x => 10, y => 10 }); |
1390c23d |
98 | |
99 | ## methods to freeze/thaw into |
100 | ## a specified serialization format |
101 | ## (in this case JSON) |
102 | |
103 | # pack the class into a JSON string |
c1830046 |
104 | $p->freeze(); # { "__CLASS__" : "Point-0.01", "x" : 10, "y" : 10 } |
1390c23d |
105 | |
106 | # unpack the JSON string into a class |
c1830046 |
107 | my $p2 = Point->thaw('{ "__CLASS__" : "Point-0.01", "x" : 10, "y" : 10 }'); |
1390c23d |
108 | |
109 | ## methods to load/store a class |
110 | ## on the file system |
111 | |
112 | $p->store('my_point.json'); |
113 | |
114 | my $p2 = Point->load('my_point.json'); |
115 | |
ec9c1923 |
116 | =head1 DESCRIPTION |
117 | |
1390c23d |
118 | MooseX::Storage is a serialization framework for Moose, it provides |
119 | a very flexible and highly pluggable way to serialize Moose classes |
120 | to a number of different formats and styles. |
121 | |
7b428d1f |
122 | =head2 Important Note |
123 | |
124 | This is still an early release of this module, so use with caution. |
125 | It's outward facing serialization API should be considered stable, |
126 | but I still reserve the right to make tweaks if I need too. Anything |
127 | beyond the basic pack/unpack, freeze/thaw and load/store should not |
128 | be relied on. |
129 | |
1390c23d |
130 | =head2 Levels of Serialization |
131 | |
132 | There are 3 levels to the serialization, each of which builds upon |
133 | the other and each of which can be customized to the specific needs |
134 | of your class. |
135 | |
136 | =over 4 |
137 | |
138 | =item B<base> |
139 | |
140 | The first (base) level is C<pack> and C<unpack>. In this level the |
141 | class is serialized into a Perl HASH reference, it is tagged with the |
142 | class name and each instance attribute is stored. Very simple. |
143 | |
144 | This level is not optional, it is the bare minumum that |
145 | MooseX::Storage provides and all other levels build on top of this. |
146 | |
147 | =item B<format> |
148 | |
149 | The second (format) level is C<freeze> and C<thaw>. In this level the |
150 | output of C<pack> is sent to C<freeze> or the output of C<thaw> is sent |
151 | to C<unpack>. This levels primary role is to convert to and from the |
152 | specific serialization format and Perl land. |
153 | |
154 | This level is optional, if you don't want/need it, you don't have to |
155 | have it. You can just use C<pack>/C<unpack> instead. |
156 | |
157 | =item B<io> |
158 | |
159 | The third (io) level is C<load> and C<store>. In this level we are reading |
160 | and writing data to file/network/database/etc. |
161 | |
124c2ba5 |
162 | This level is also optional, in most cases it does require a C<format> role |
163 | to also be used, the expection being the C<StorableFile> role. |
1390c23d |
164 | |
165 | =back |
166 | |
167 | =head2 How we serialize |
168 | |
169 | There are always limits to any serialization framework, there are just |
170 | some things which are really difficult to serialize properly and some |
171 | things which cannot be serialized at all. |
172 | |
173 | =head2 What can be serialized? |
174 | |
175 | Currently only numbers, string, ARRAY refs, HASH refs and other |
176 | MooseX::Storage enabled objects are supported. |
177 | |
178 | With Array and Hash references the first level down is inspected and |
179 | any objects found are serialized/deserialized for you. We do not do |
180 | this recusively by default, however this feature may become an |
181 | option eventually. |
182 | |
183 | The specific serialize/deserialize routine is determined by the |
184 | Moose type constraint a specific attribute has. In most cases subtypes |
185 | of the supported types are handled correctly, and there is a facility |
186 | for adding handlers for custom types as well. This will get documented |
187 | eventually, but it is currently still in development. |
188 | |
189 | =head2 What can not be serialized? |
190 | |
191 | We do not support CODE references yet, but this support might be added |
192 | in using B::Deparse or some other deep magic. |
193 | |
194 | Scalar refs are not supported, mostly because there is no way to know |
195 | if the value being referenced will be there when the object is inflated. |
196 | I highly doubt will be ever support this in a general sense, but it |
197 | would be possible to add this yourself for a small specific case. |
198 | |
199 | Circular references are specifically disallowed, however if you break |
200 | the cycles yourself then re-assemble them later you can get around this. |
201 | The reason we disallow circular refs is because they are not always supported |
202 | in all formats we use, and they tend to be very tricky to do for all |
203 | possible cases. It is almost always something you want to have tight control |
204 | over anyway. |
205 | |
206 | =head1 CAVEAT |
207 | |
208 | This is B<not> a persistence framework, changes to your object after |
209 | you load or store it will not be reflected in the stored class. |
210 | |
211 | =head1 EXPORTS |
212 | |
213 | =over 4 |
214 | |
215 | =item B<Storage (%options)> |
216 | |
217 | This module will export the C<Storage> method will can be used to |
218 | load a specific set of MooseX::Storage roles to implement a specific |
219 | combination of features. It is meant to make things easier, but it |
220 | is by no means the only way. You can still compose your roles by |
221 | hand if you like. |
222 | |
223 | =back |
224 | |
ec9c1923 |
225 | =head1 METHODS |
226 | |
227 | =over 4 |
228 | |
229 | =item B<import> |
230 | |
231 | =back |
232 | |
233 | =head2 Introspection |
234 | |
235 | =over 4 |
236 | |
237 | =item B<meta> |
238 | |
239 | =back |
240 | |
1390c23d |
241 | =head1 TODO |
242 | |
7b428d1f |
243 | This module needs docs and probably a Cookbook of some kind as well. |
244 | This is an early release, so that is my excuse for now :) |
1390c23d |
245 | |
246 | For the time being, please read the tests and feel free to email me |
247 | if you have any questions. This module can also be discussed on IRC |
248 | in the #moose channel on irc.perl.org. |
249 | |
ec9c1923 |
250 | =head1 BUGS |
251 | |
252 | All complex software has bugs lurking in it, and this module is no |
253 | exception. If you find a bug please either email me, or add the bug |
254 | to cpan-RT. |
255 | |
256 | =head1 AUTHOR |
257 | |
258 | Chris Prather E<lt>chris.prather@iinteractive.comE<gt> |
259 | |
260 | Stevan Little E<lt>stevan.little@iinteractive.comE<gt> |
261 | |
6c9f2c85 |
262 | Yuval Kogman E<lt>yuval.kogman@iinteractive.comE<gt> |
263 | |
ec9c1923 |
264 | =head1 COPYRIGHT AND LICENSE |
265 | |
1f3074ea |
266 | Copyright 2007-2008 by Infinity Interactive, Inc. |
ec9c1923 |
267 | |
268 | L<http://www.iinteractive.com> |
269 | |
270 | This library is free software; you can redistribute it and/or modify |
271 | it under the same terms as Perl itself. |
e9739624 |
272 | |
273 | =cut |