naoyaの日記 RSSフィード

 | 

2006-03-15

Publish::Serializer 23:40

Data::Serializer を使うように変更。config.yml で serializer を指定することでいろんなフォーマットで書き出せる。

  - module: Publish::Serializer
    config:
      serializer: YAML
      dir: /Users/naoya/tmp
      filename: test.yml

シリアライズは Data::Serializer が面倒をみることになり、サブクラスを用意する必要はなくなった。raw_serialize してるので Data::Serializer の圧縮とか暗号オプションとか使えないけども。

package Plagger::Plugin::Publish::Serializer;
use strict;
use warnings;
use base qw (Plagger::Plugin);

use File::Spec;
use IO::File;
use Data::Serializer;

sub serialize {
    my ($self, $data) = @_;
    my $option = $self->conf->{option} || {};
    my $selializer =  Data::Serializer->new(
        serializer => $self->conf->{serializer} || 'Data::Dumper',
    );
    $selializer->raw_serialize($data);
}

sub register {
    my ($self, $context) = @_;
    $context->register_hook(
        $self,
        'publish.feed' => \&feed,
    );
}

sub feed2data {
    my ($self, $feed) = @_;
    my $data = {
        feed => {
            title => $feed->title,
            link  => $feed->link,
            generator => join('/', 'Plagger', $Plagger::VERSION),
        }
    };
    for my $entry ($feed->entries) {
        my $eobj = {};
        $eobj->{$_} = $entry->$_ for qw(title link body author tags);
        push @{$data->{feed}->{entries}}, $eobj;
    }
    $data;
}

sub feed {
    my ($self, $context, $args) = @_;
    my $dir = $self->conf->{dir};
    unless (-e $dir && -d _) {
        mkdir $dir, 0755 or $context->error("mkdir $dir: $!");
    }
    my $file = $self->gen_filename($args->{feed}) ||
        $args->{feed}->id . __PACKAGE__->default_file_extention;
    my $path = File::Spec->catfile($dir, $file);
    my $serialized = $self->serialize(
        $self->feed2data($args->{feed})
    );
    my $io = IO::File->new("> $path");
    $io->print($serialized);
    $io->close;
    $context->log(
        info => sprintf(
            "Write to %s: %d entries",
            $path,
            $args->{feed}->count
        )
    );
}

my %formats = (
    'u' => sub { my $s = $_[0]->url;  $s =~ s!^https?://!!; $s },
    'l' => sub { my $s = $_[0]->link; $s =~ s!^https?://!!; $s },
    't' => sub { $_[0]->title },
    'i' => sub { $_[0]->id },
);

my $format_re = qr/%(u|l|t|i)/;

sub gen_filename {
    my($self, $feed) = @_;

    my $file = $self->conf->{filename} || '';
    $file =~ s{$format_re}{
        $self->safe_filename($formats{$1}->($feed))
    }egx;

    $file;
}

sub safe_filename {
    my($self, $path) = @_;
    $path =~ s![^\w\s]+!_!g;
    $path =~ s!\s+!_!g;
    $path;
}

1;

ただ、Data::Serializer は JSONサポートしてない。そもそもこのプラグインを作ったのはフィードJSON に変換したかったからなのだよママン。

ということで Data::Serializer::JSON を作る。

package Data::Serializer::JSON;
BEGIN { @Data::Serializer::JSON::ISA = qw(Data::Serializer) }

use strict;
use JSON;
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);

require Exporter;
require AutoLoader;

@ISA = qw(Exporter AutoLoader);
@EXPORT = qw(

);
$VERSION = '0.01';

1;
__END__

=head1 NAME

Data::Serializer::JSON - Creates bridge between Data::Serializer and Storable

=head1 SYNOPSIS

  use Data::Serializer::JSON;

=head1 DESCRIPTION

Module is used internally to Data::Serializer

=head1 AUTHOR

Naoya Ito <naoya@bloghackers.net>

=head1 COPYRIGHT

  This program is free software; you can redistribute it
  and/or modify it under the same terms as Perl itself.

=head1 SEE ALSO

perl(1), Data::Serializer(3), JSON(3).

=cut

sub serialize {
    return JSON->new->objToJson($_[1]);
}

sub deserialize {
    return JSON->new->jsonToObj($_[1]);
}

Data::Serializer の他のクラスの実装に併せて作ってるのでちょっとださいけどまあしゃあない。AutoLoader を使う必要があるので AutoSplit が走るように make を実行したりとかがめんどい

よし、作者にパッチを送ろうとおもったがしかし、Data::Serializer のテストが超わかんない。しょうがないのでテスト放置でついでに JSON::Syck と YAML::Syck も作った。

package Data::Serializer::YAML::Syck;
BEGIN { @Data::Serializer::YAML::Syck::ISA = qw(Data::Serializer) }

use strict;
use YAML::Syck;
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);

require Exporter;
require AutoLoader;

@ISA = qw(Exporter AutoLoader);
@EXPORT = qw(
	
);
$VERSION = '0.01';

1;
__END__

sub serialize {
    return Dump($_[1]);
}

sub deserialize {
    return Load($_[1]);
}
package Data::Serializer::JSON::Syck;
BEGIN { @Data::Serializer::JSON::Syck::ISA = qw(Data::Serializer) }

use strict;
use JSON::Syck;
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);

require Exporter;
require AutoLoader;

@ISA = qw(Exporter AutoLoader);
@EXPORT = qw(
	
);
$VERSION = '0.01';

1;
__END__

sub serialize {
    return Dump($_[1]);
}

sub deserialize {
    return Load($_[1]);
}

YAML.pm と比べてもそれぞれ一行しか違わないんだけど。全然 DRY じゃない!

hori-uchihori-uchi2006/03/15 10:16僕もamazonから来てた!

TigerTiger2006/03/15 12:00全部が全部、2/15に実施ではないということで、ポロッポロッと話題になりますね (^^;

トラックバック - http://naoya.g.hatena.ne.jp/naoya/20060315
 | 
この日記のはてなブックマーク数