Ambrosia
view release on metacpan or search on metacpan
lib/Ambrosia/EntityDataModel.pm view on Meta::CPAN
else
{
return $h->{$key_name};
}
}
################################################################################
# END
################################################################################
sub get_cache_code
{
my $proto = shift;
if ( my $class = ref $proto )
{
my $id = $proto->key_value();
return $class . '_' . join '_', (ref $id ? @$id : $id);
}
else
{
my $id = shift();
if ( defined $id )
{
return $proto . '_' . join '_', (ref $id ? @$id : $id);
}
else
{
die 'Bad usage get_cache_code: ' . $proto . '; '
. join('; ', caller(0), "\n")
. join('; ', caller(1), "\n")
. join('; ', caller(2), "\n");
}
}
}
sub after_load
{
@_;
}
sub list
{
my $proto = shift;
my $class = ref($proto) || $proto;
my $offset = shift;
my $limit = shift;
my $count = shift;
my $driver = storage->driver($class->driver_type, $class->source_name);
assert {$driver} 'Not defined driver';
return new Ambrosia::core::Nil unless $driver;
my $source_path = join '_', grep defined $_, $class->source_path();
my $entity;
my $query = Ambrosia::QL
->from([$class->source_path()], \$entity)
->in($driver)
->what($class->fields_mapping)
->select(sub {
my %h = map { my $v = $entity->{$_}; s/^${source_path}_//; $_ => $v } keys %$entity;
if ( my $old = $driver->cache->get($class->get_cache_code($class->id_value_from_hash(\%h))) )
{
return $old;
}
my $e = $class->new(%h);
$driver->cache->set($e->get_cache_code, $e);
$e->after_load;
return $e;
});
my $list;
if ( $limit )
{
$query->skip($offset || 0);
}
if ( $count )
{
($list, $count) = $query->count($limit);
return ($list, $count);
}
else
{
$list = [$query->take($limit)];
}
return ($list, undef);
}
sub load
{
my $proto = shift;
my $class = ref($proto) || $proto;
my $id = shift;
my @val = ref $id ? @{$id} : $id;
return undef unless scalar @val && defined $val[0] && $val[0] ne '';
my $driver = storage->driver($class->driver_type, $class->source_name);
assert {$driver} 'Not defined driver';
return new Ambrosia::core::Nil unless $driver;
if ( my $old = $driver->cache->get($class->get_cache_code($id)) )
{
return $old;
}
my $entity;
my $query = Ambrosia::QL
->from([$class->source_path()], \$entity)
->in($driver)
->what($class->fields_mapping);
my $key = $class->key;
foreach ( ref $key ? @$key : ($key) )
{
$query->predicate($_, '=', shift(@val));
}
my $source_path = join '_', grep defined $_, $class->source_path();
my @new_e = $query->select(sub {
my %h = map { my $v = $entity->{$_}; s/^${source_path}_//; $_ => $v } keys %$entity;
if ( my $old = $driver->cache->get($class->get_cache_code($class->id_value_from_hash(\%h))) )
{
return $old;
}
my $e = $class->new(%h);
$driver->cache->set($e->get_cache_code, $e);
$e->after_load;
return $e;
})->take(1);
return $new_e[0];
}
################################################################################
#ÐÑзÑваеÑÑÑ Ð¸Ð· save пеÑед ÑоÑмиÑованием запÑоÑа к базе.
sub before_save
{
1;
}
sub after_save
{
1;
}
sub save
{
my $self = shift;
return $self if $self->IS_SAVED;
return new Ambrosia::core::Nil unless $self->before_save(@_);
if ( $self->need_insert )
{
$self->insert;
}
elsif ( $self->need_update )
{
$self->update;
}
else
{
assert {0} 'Unknown state="' . $self->_state . '"';
return new Ambrosia::core::Nil;
}
$self->SET_SAVED;
$self->after_save(@_);
return $self;
}
#catalog -- schema(db name) -- table
sub insert
{
my $self = shift;
my $driver = storage->driver($self->driver_type, $self->source_name);
assert {$driver} 'Unknown source for insert data: ' . ($self->source_name || 'undefined source');
return new Ambrosia::core::Nil unless $driver;
lib/Ambrosia/EntityDataModel.pm view on Meta::CPAN
my $self = shift;
my $driver = storage->driver($self->driver_type, $self->source_name);
assert {$driver} 'Unknown source for delete data: ' . ($self->source_name || 'undefined source');
return new Ambrosia::core::Nil unless $driver;
my %cond = @_;
my $q = $driver->reset()
->source( $self->source_path() )
->delete();
foreach ( keys %cond )
{
$q->predicate($_, '=', $cond{$_});
}
$q->execute(0);
if ( ref $self )
{
$driver->cache->delete($self->get_cache_code());
}
}
sub update
{
my $self = shift;
my $driver = storage->driver($self->driver_type, $self->source_name);
assert {$driver} 'Unknown source for update data: ' . ($self->source_name || 'undefined source');
return new Ambrosia::core::Nil unless $driver;
my $q = $driver->reset()
->source( $self->source_path() )
->update()
->what( $self->fields_mapping() );
foreach ( pare_list($self->key, $self->key_value) )
{
$q->predicate($_->[0], '=', $_->[1]);
}
$q->execute($self->value($self->edit_fields));
}
sub find
{
my $proto = shift;
my $class = ref($proto) || $proto;
my $var = shift || my $entity;
my $driver = storage->driver($class->driver_type, $class->source_name);
assert {$driver} 'Unknown source for find data: ' . ($class->source_name || 'undefined source');
return new Ambrosia::core::Nil unless $driver;
my $source_path = join '_', grep defined $_, $class->source_path();
return Ambrosia::EntityDataModel::_find->new(
edm => $class,
var => \$var,
query => Ambrosia::QL
->from([$class->source_path()], \$var)
->in($driver)
->what($class->fields_mapping)
->select(sub {
my %h = map { my $v = $var->{$_}; s/^${source_path}_//; $_ => $v } keys %$var;
%$var = %h;
if ( my $old = $driver->cache->get($class->get_cache_code($class->id_value_from_hash(\%h))) )
{
return $old;
}
my $e = $class->new(%h);
$driver->cache->set($e->get_cache_code, $e);
$e->after_load;
return $e;
})
);
}
sub link_one2one
{
no strict 'refs';
my $proto = shift;
my %params = @_;
my $type = $params{type};
my $pk = $params{from};
my $yeld = $params{optional}
? sub {new Ambrosia::core::Nil}
: sub {throw Ambrosia::error::Exception shift};
if ( $type->primary_key && $type->primary_key eq $params{to} )
{
*{$proto . '::' . $params{name}} = sub() {
my $self = shift;
return ($self->$pk ? $type->load($self->$pk) : undef)
|| $yeld->('Wrong relationship for ' . $type . ': ' . $pk . '=' . $self->$pk);
};
}
else
{
my @key = ref $params{to} ? @{$params{to}} : $params{to};
my @val = ref $params{from} ? @{$params{from}} : $params{from};
my $condition = sub {shift(), shift()};
while( my $k = shift(@key) )
{
my $v = shift(@val);
my $old = $condition;
$condition = sub { my $self = shift; my $q = shift; $old->($self, $q)->predicate($k, '=', $self->$v); $q; }
}
*{$proto . '::' . $params{name}} = sub() {
my $self = shift;
return
($condition->($self, $type->find())->take(1))[0]
|| $yeld->('Wrong relationship: not found entity of ' . $type . ' for ' . $proto . ': '
. join(',', @key)
. ' [' . join(',', map {$self->$_} (ref $params{from} ? @{$params{from}} : $params{from})) . ']'
);
};
}
}
( run in 0.564 second using v1.01-cache-2.11-cpan-39bf76dae61 )