comment saving
[scpubgit/Commentry.git] / lib / App / Commentry / CommentSet.pm
1 package App::Commentry::CommentSet;
2
3 use aliased 'App::Commentry::Comment';
4 use JSON;
5 use File::Spec;
6 use File::Path;
7 use File::Copy;
8 use Moo;
9
10 has base_dir => (is => 'ro', required => 1);
11 has path => (is => 'ro', required => 1);
12
13 has _json => (is => 'lazy');
14
15 sub _build__json { JSON->new->utf8->pretty->convert_blessed }
16
17 has _members => (is => 'lazy');
18
19 sub _filename {
20   my ($self) = @_;
21   File::Spec->catfile($self->base_dir, $self->path.'.json');
22 }
23
24 sub _build__members {
25   my ($self) = @_;
26   my $file = $self->_filename;
27   return [] unless -e $file;
28   my $text = do {
29     open my $in, '<', $file
30       or die "Couldn't open ${file}: $!";
31     local $/; <$in>;
32   };
33   [ map Comment->new($_), @{$self->_json->decode($text)} ];
34 }
35
36 sub _write {
37   my ($self) = @_;
38   my $file = $self->_filename;
39   mkpath((File::Spec->splitpath($file))[1]);
40   open my $out, '>', "${file}.new"
41     or die "Couldn't open ${file}.new to write: $!";
42   print $out $self->_json->encode($self->_members);
43   move("${file}.new", $file);
44 }
45
46 sub flatten {
47   my ($self) = @_;
48   @{$self->_members};
49 }
50
51 sub map {
52   my ($self, $mapping) = @_;
53   require App::Commentry::MappedSet;
54   App::Commentry::MappedSet->new(source => $self, mapping => $mapping);
55 }
56
57 sub add {
58   my ($self, $params) = @_;
59   push @{$self->_members}, my $new = Comment->new($params);
60   $self->_write;
61   $new;
62 }
63
64 1;