CouchDB-Client

 view release on metacpan or  search on metacpan

lib/CouchDB/Client/Doc.pm  view on Meta::CPAN


package CouchDB::Client::Doc;

use strict;
use warnings;

our $VERSION = $CouchDB::Client::VERSION;

use HTTP::Request   qw();
use URI::Escape     qw(uri_escape_utf8);
use MIME::Base64    qw(encode_base64);
use Carp            qw(confess);

sub new {
	my $class = shift;
	my %opt = @_ == 1 ? %{$_[0]} : @_;

	confess "Doc needs a database" unless $opt{db};

	my %self = (
		id          => $opt{id} || '',
		rev         => $opt{rev} || '',
		attachments => $opt{attachments} || {},
		data        => $opt{data} || {},
		db          => $opt{db},
	);
	return bless \%self, $class;
}

sub id { return $_[0]->{id}; }
sub rev { return $_[0]->{rev}; }

sub data {
	my $self = shift;
	if (@_) {
		my $data = shift;
		$self->{attachments} = delete($data->{_attachments}) || {};
		$self->{data} = $data;
	}
	else {
		return $self->{data};
	}
}
sub attachments { @_ == 2 ? $_[0]->{attachments} = $_[1] : $_[0]->{attachments}; }

sub uriName {
	my $self = shift;
	return undef unless $self->{id};
	return $self->{db}->uriName . '/' . uri_escape_utf8($self->{id});
}

sub create {
	my $self = shift;

	confess("Object already had a revision") if $self->{rev};

	my $content = $self->contentForSubmit;
	my $res;
	if ($self->{id}) {
		$res = $self->{db}->{client}->req('PUT', $self->uriName, $content);
	}
	else {
		$res = $self->{db}->{client}->req('POST', $self->{db}->uriName, $content);
	}
	confess("Storage error: $res->{msg}") unless $res->{success};
	$self->{rev} = $res->{json}->{rev};
	$self->{id} = $res->{json}->{id} unless $self->{id};
	return $self;
}

lib/CouchDB/Client/Doc.pm  view on Meta::CPAN

	my $res = $self->{db}->{client}->req('GET', $self->uriName . '?rev=' . $rev);
	confess("Object not found: $res->{msg}") if $res->{status} == 404;
	confess("Connection error: $res->{msg}") unless $res->{success};
	my $data = $res->{json};
	my %private;
	my @keys = keys %$data; # need to two-step this due to delete()
	for my $k (@keys) {
		if ($k =~ m/^_(.+)/) {
			$private{$1} = delete $data->{$k};
		}
	}
	return ref($self)->new({
		id          => $self->id,
		rev         => $rev,
		attachments => $private{attachments},
		data        => $data,
		db          => $self->{db},
	});
}

sub revisionsInfo {
	my $self = shift;

	my $res = $self->{db}->{client}->req('GET', $self->uriName . '?revs_info=true');
	confess("Object not found: $res->{msg}") if $res->{status} == 404;
	confess("Connection error: $res->{msg}") unless $res->{success};
	return $res->{json}->{_revs_info};
}

sub update {
	my $self = shift;

	confess("Object hasn't been retrieved") unless $self->{id} and $self->{rev};
	my $content = $self->contentForSubmit;
	my $res = $self->{db}->{client}->req('PUT', $self->uriName, $content);
	confess("Storage error: $res->{msg}") unless $res->{success};
	$self->{rev} = $res->{json}->{rev};
	return $self;
}

sub delete {
	my $self = shift;

	confess("Object hasn't been retrieved") unless $self->{id} and $self->{rev};
	my $res = $self->{db}->{client}->req('DELETE', $self->uriName . "?rev=" . $self->rev);
	confess("Object not found: $res->{msg}") if $res->{status} == 404;
	confess("Connection error: $res->{msg}") unless $res->{success};
	$self->{deletion_stub_rev} = $res->{json}->{rev};
	$self->{rev} = '';
	$self->{data} = {};
	$self->{attachments} = {};
	return $self;
}

sub fetchAttachment {
	my $self = shift;
	my $attName = shift;

	confess("No such attachment: '$attName'") unless exists $self->{attachments}->{$attName};
	my $res = $self->{db}->{client}->{ua}->request(
		HTTP::Request->new('GET', $self->{db}->{client}->uriForPath($self->uriName . '/' . uri_escape_utf8($attName)))
	);
	return $res->content if $res->is_success;
	confess("Object not found: $res->{msg}");
}

sub addAttachment {
	my $self = shift;
	my $name = shift;
	my $ctype = shift;
	my $data = shift;

	$self->{attachments}->{$name} = {
		content_type    => $ctype,
		data            => $self->toBase64($data),
	};
	return $self;
}

sub deleteAttachment {
	my $self = shift;
	my $attName = shift;

	confess("No such attachment: '$attName'") unless exists $self->{attachments}->{$attName};
	delete $self->{attachments}->{$attName};
	return $self;
}

sub toBase64 {
	my $self = shift;
	my $data = shift;

	my $ret = encode_base64 $data;
	$ret =~ s/\n//g;
	return $ret;
}

1;

=pod

=head1 NAME

CouchDB::Client::Doc - CouchDB::Client document

=head1 SYNOPSIS

	$doc->data->{foo} = 'new bar';
	$doc->addAttachment('file.xml', 'application/xml', '<foo/>);
	$doc->update;
	$doc->delete;

=head1 DESCRIPTION

This module represents documents in the CouchDB database.

We don't yet deal with a number of options such as retrieving revisions and
revision status.

=head1 METHODS



( run in 0.609 second using v1.01-cache-2.11-cpan-39bf76dae61 )