view release on metacpan or search on metacpan
lib/ActiveRecord/Simple.pm view on Meta::CPAN
package ActiveRecord::Simple;
use 5.010;
use strict;
use warnings;
our $VERSION = '1.11';
use utf8;
use Carp;
use Scalar::Util qw/blessed/;
use ActiveRecord::Simple::QueryManager;
use ActiveRecord::Simple::Utils qw/all_blessed class_to_table_name load_module/;
use ActiveRecord::Simple::Connect;
our $connector;
my $qm = ActiveRecord::Simple::QueryManager->new();
sub new {
my $class = shift;
my $params = (scalar @_ > 1) ? {@_} : $_[0];
# relations
$class->_init_relations if $class->can('_get_relations');
return bless $params || {}, $class;
}
sub auto_load {
my ($class) = @_;
my $table_name = class_to_table_name($class);
# 0. check the name
my $table_info_sth = $class->dbh->table_info('', '%', $table_name, 'TABLE');
$table_info_sth->fetchrow_hashref or croak "Can't find table '$table_name' in the database";
lib/ActiveRecord/Simple.pm view on Meta::CPAN
sub _find_many_to_many { ActiveRecord::Simple::Find->_find_many_to_many(shift, @_) }
sub DESTROY {}
### Private
sub _get_primary_key_value {
my ($self) = @_;
croak "Sory, you can call method '_get_primary_key_value' on unblessed scalar."
unless blessed $self;
my $pk = $self->_get_primary_key;
return $self->$pk;
}
sub _get_relation_type {
my ($class, $relation) = @_;
my $type = $relation->{type};
lib/ActiveRecord/Simple.pm view on Meta::CPAN
my $pk = $relation->{params}{pk};
my $fk = $relation->{params}{fk};
my $instance_name = "relation_instance_$relation_name";
if (grep { $full_relation_type eq $_ } qw/one_to_many one_to_one one_to_only/) {
*{$pkg_method_name} = sub {
my ($self, @args) = @_;
if (@args) {
my $object = shift @args;
croak "Using unblessed scalar as an object reference"
unless blessed $object;
$object->save() if ! exists $object->{isin_database} && !$object->{isin_database} == 1;
#$self->$fk($object->$pk);
$self->{$fk} = $object->{$pk};
$self->{$instance_name} = $object;
return $self;
}
# else
lib/ActiveRecord/Simple.pm view on Meta::CPAN
}
return $self->{$instance_name};
}
}
elsif ($full_relation_type eq 'many_to_one') {
*{$pkg_method_name} = sub {
my ($self, @args) = @_;
if (@args) {
unless (all_blessed(\@args)) {
return $related_class->find(@args)->left_join($self->_get_table_name);
}
OBJECT:
for my $object (@args) {
next OBJECT if !blessed $object;
my $pk = $self->_get_primary_key;
#$object->$fk($self->$pk)->save;
$object->{$fk} = $self->{$pk};
$object->save();
}
return $self;
}
# else
lib/ActiveRecord/Simple.pm view on Meta::CPAN
}
}
elsif ($full_relation_type eq 'many_to_many') {
*{$pkg_method_name} = sub {
my ($self, @args) = @_;
if (@args) {
my $related_subclass = _get_related_subclass($relation);
unless (all_blessed(\@args)) {
return $related_class->_find_many_to_many({
root_class => $class,
via_table => $relation->{via_table},
m_class => $related_subclass,
self => $self,
where_statement => \@args,
});
}
lib/ActiveRecord/Simple.pm view on Meta::CPAN
$fk2 = $related_class_relation->{params}{fk};
}
my $pk1_name = $self->_get_primary_key;
my $pk1 = $self->{$pk1_name};
defined $pk1 or croak 'You are trying to create relations between unsaved objects. Save your ' . $class . ' object first';
OBJECT:
for my $object (@args) {
next OBJECT if !blessed $object;
my $pk2_name = $object->_get_primary_key;
my $pk2 = $object->{$pk2_name};
$related_subclass->new($fk1 => $pk1, $fk2 => $pk2)->save;
}
}
else {
my ($fk1, $fk2);
$fk1 = $fk;
$fk2 = class_to_table_name($related_class) . '_id';
my $pk1_name = $self->_get_primary_key;
my $pk1 = $self->{$pk1_name};
my $via_table = $relation->{via_table};
OBJECT:
for my $object (@args) {
next OBJECT if !blessed $object;
my $pk2_name = $object->_get_primary_key;
my $pk2 = $object->{$pk2_name};
my $sql = qq/INSERT INTO "$via_table" ("$fk1", "$fk2") VALUES (?, ?)/;
$self->dbh->do($sql, undef, $pk1, $pk2);
}
}
return $self;
lib/ActiveRecord/Simple.pm view on Meta::CPAN
=head2 update
Update object using hashref
$user->update({ last_login => \'NOW()' });
=head2 to_hash
Unbless object, get naked hash
=head2 increment
Increment fields
$customer->increment('age')->save;
=head2 decrement
lib/ActiveRecord/Simple/Connect.pm view on Meta::CPAN
if (!$self) {
$self = { dbh => undef };
if ($dsn) {
$self->{dsn} = $dsn;
$self->{username} = $username if $username;
$self->{password} = $password if $password;
$self->{connection_parameters} = $params if $params;
}
bless $self, $class;
}
return $self;
}
sub db_connect {
my ($self) = @_;
$self->{dbh} = DBI->connect(
$self->{dsn},
lib/ActiveRecord/Simple/Find.pm view on Meta::CPAN
use ActiveRecord::Simple::Utils qw/load_module/;
our $MAXIMUM_LIMIT = 100_000_000_000;
sub new {
my ($self_class, $class, @param) = @_;
#my $self = $class->new();
my $self = bless { class => $class } => $self_class;
my $table_name = ($self->{class}->can('_get_table_name')) ? $self->{class}->_get_table_name : undef;
my $pkey = ($self->{class}->can('_get_primary_key')) ? $self->{class}->_get_primary_key : undef;
croak 'can not get table_name for class ' . $self->{class} unless $table_name;
#croak 'can not get primary_key for class ' . $self->{class} unless $pkey;
$self->{prep_select_fields} //= [];
$self->{prep_select_from} //= [];
$self->{prep_select_where} //= [];
lib/ActiveRecord/Simple/QueryManager.pm view on Meta::CPAN
package ActiveRecord::Simple::QueryManager;
use ActiveRecord::Simple::Find;
sub new { bless {}, shift }
sub all { ActiveRecord::Simple::Find->new(shift->{caller})->fetch }
sub get { ActiveRecord::Simple::Find->new(shift->{caller}, @_)->fetch }
sub find { ActiveRecord::Simple::Find->new(shift->{caller}, @_) }
sub sql_fetch_all {
my ($self, $sql, @bind) = @_;
my $data = $self->{caller}->dbh->selectall_arrayref($sql, { Slice => {} }, @bind);
my @list;
for my $row (@$data) {
$self->{caller}->_mk_ro_accessors([keys %$row]);
bless $row, $self->{caller};
push @list, $row;
}
return \@list;
}
sub sql_fetch_row {
my ($self, $sql, @bind) = @_;
my $row = $self->{caller}->dbh->selectrow_hashref($sql, undef, @bind);
$self->{caller}->_mk_ro_accessors([keys %$row]);
bless $row, $self->{caller};
return $row;
}
1;
__END__;
=head1 NAME
lib/ActiveRecord/Simple/Utils.pm view on Meta::CPAN
package ActiveRecord::Simple::Utils;
use strict;
use warnings;
require Exporter;
use Module::Load;
use Module::Loaded;
use Scalar::Util qw/blessed/;
our @ISA = qw/Exporter/;
our @EXPORT = qw/class_to_table_name all_blessed load_module/;
sub quote_sql_stmt {
my ($sql, $driver_name) = @_;
return unless $sql && $driver_name;
$driver_name //= 'Pg';
my $quotes_map = {
Pg => q/"/,
lib/ActiveRecord/Simple/Utils.pm view on Meta::CPAN
sub is_numeric {
my ($data_type) = @_;
return unless $data_type;
return 1 if is_integer($data_type);
return grep { $data_type eq $_ } qw/numeric decimal/;
}
sub all_blessed {
my ($list) = @_;
for my $item (@$list) {
return unless defined $item;
return unless blessed $item;
}
return 1;
}
sub load_module {
my ($module_name) = @_;
if (!is_loaded $module_name) {
eval { load $module_name; };
t/08-basic.t view on Meta::CPAN
use base 'ActiveRecord::Simple';
package MockDBI;
sub selectrow_array { 1 }
sub do { 1 }
sub selectrow_hashref { { DUMMY => 'hash' } }
sub fetchrow_hashref { { DUMMY => 'hash' } }
sub prepare { bless {}, 'MockDBI' }
sub execute { 1 }
sub last_insert_id { 1 }
sub selectall_arrayref { [{ foo => 1 }, { bar => 2 }] }
1;
*ActiveRecord::Simple::dbh = sub {
return bless { Driver => { Name => 'mysql' } }, 'MockDBI';
};
package main;
use Test::More;
ok my $c = t::class->new({
foo => 1,
bar => 2,
});
t/12-connect.t view on Meta::CPAN
use strict;
use warnings;
use 5.010;
use FindBin '$Bin';
use lib "$Bin/../lib";
use Data::Dumper;
use DBI;
#use Scalar::Util qw/blessed/;
package Customer;
use parent 'ActiveRecord::Simple';
__PACKAGE__->table_name('customers');
__PACKAGE__->primary_key('id');
__PACKAGE__->columns(qw/id first_name second_name age email/);