DBIx-Class-Helpers
view release on metacpan or search on metacpan
lib/DBIx/Class/Helper/Row/OnColumnChange.pm view on Meta::CPAN
use List::Util 'first';
use DBIx::Class::Candy::Exports;
use namespace::clean;
export_methods [qw(before_column_change around_column_change after_column_change)];
__PACKAGE__->mk_group_accessors(inherited => $_)
for qw(_before_change _around_change _after_change);
sub before_column_change {
die 'Invalid number of arguments. One $column => $args pair at a time.'
unless @_ == 3;
my $self = shift;
my $column = shift;
my $args = shift;
die 'method is a required parameter' unless $args->{method};
$args->{column} = $column;
$args->{txn_wrap} = !!$args->{txn_wrap};
$self->_before_change([]) unless $self->_before_change;
push @{$self->_before_change}, $args;
}
sub around_column_change {
die 'Invalid number of arguments. One $column => $args pair at a time.'
unless @_ == 3;
my $self = shift;
my $column = shift;
my $args = shift;
die 'no method passed!' unless $args->{method};
$args->{column} = $column;
$args->{txn_wrap} = !!$args->{txn_wrap};
$self->_around_change([]) unless $self->_around_change;
push @{$self->_around_change}, $args;
}
sub after_column_change {
die 'Invalid number of arguments. One $column => $args pair at a time.'
unless @_ == 3;
my $self = shift;
my $column = shift;
my $args = shift;
die 'no method passed!' unless $args->{method};
$args->{column} = $column;
$args->{txn_wrap} = !!$args->{txn_wrap};
$self->_after_change([]) unless $self->_after_change;
unshift @{$self->_after_change}, $args;
}
sub update {
my ($self, $args) = @_;
$self->set_inflated_columns($args) if $args;
my %dirty = $self->get_dirty_columns
or return $self;
my @all_before = @{$self->_before_change || []};
my @all_around = @{$self->_around_change || []};
my @all_after = @{$self->_after_change || []};
# prepare functions
my @before = grep { defined $dirty{$_->{column}} } @all_before;
my @around = grep { defined $dirty{$_->{column}} } @all_around;
my @after = grep { defined $dirty{$_->{column}} } @all_after;
my $inner = $self->next::can;
my $final = $self->on_column_change_allow_override_args
? sub { $self->$inner }
: sub { $self->$inner($args) };
for ( reverse @around ) {
my $fn = $_->{method};
my $old = $self->get_storage_value($_->{column});
my $new = $dirty{$_->{column}};
my $old_final = $final;
$final = sub { $self->$fn($old_final, $old, $new) };
}
# do we wrap it in a transaction?
my $txn_wrap = first { defined $dirty{$_->{column}} && $_->{txn_wrap} }
@all_before, @all_around, @all_after;
my $guard;
$guard = $self->result_source->schema->txn_scope_guard if $txn_wrap;
for (@before) {
my $fn = $_->{method};
my $old = $self->get_storage_value($_->{column});
my $new = $dirty{$_->{column}};
$self->$fn($old, $new);
}
my $ret = $final->();
for (@after) {
my $fn = $_->{method};
my $old = $self->get_storage_value($_->{column});
my $new = $dirty{$_->{column}};
$self->$fn($old, $new);
}
$guard->commit if $txn_wrap;
$ret
}
sub on_column_change_allow_override_args { 0 }
( run in 1.166 second using v1.01-cache-2.11-cpan-39bf76dae61 )