DBIx-Class-Events
view release on metacpan or search on metacpan
lib/DBIx/Class/Events.pm view on Meta::CPAN
__PACKAGE__->load_components(qw/ InflateColumn::DateTime /);
__PACKAGE__->table('artist_event');
__PACKAGE__->add_columns(
artisteventid => { data_type => 'integer', is_auto_increment => 1 },
artistid => { data_type => 'integer' },
# The type of event
event => { data_type => 'varchar' },
# Any other custom columns you want to store for each event.
triggered_on => {
data_type => 'datetime',
default_value => \'NOW()',
},
# Where we store freeform data about what happened
details => { data_type => 'longtext' },
);
__PACKAGE__->set_primary_key('artisteventid');
# You should set up automatic inflation/deflation of the details column
# as it is used this way by "state_at" and the insert/update/delete
# events. Does not have to be JSON, just be able to serialize a hashref.
{
my $json = JSON->new->utf8;
__PACKAGE__->inflate_column( 'details' => {
inflate => sub { $json->decode(shift) },
deflate => sub { $json->encode(shift) },
} );
}
This L<C<belongs_to>|DBIx::Class::Relationship/belongs_to>
relationship is optional,
and the examples and tests assume if it exists,
it is not a real database-enforced foreign key
that will trigger constraint violations if the thing being tracked is deleted.
# A path back to the object that this event is for,
# not required unlike the has_many "events" relationship above
__PACKAGE__->belongs_to(
'artist' => ( 'MyApp::Schema::Result::Artist', 'artistid' ) );
You probably also want an index for searching for events:
sub sqlt_deploy_hook {
my ( $self, $sqlt_table ) = @_;
$sqlt_table->add_index(
name => 'artist_event_idx',
fields => [ "artistid", "triggered_on", "event" ],
);
}
=head1 PRECONFIGURED EVENTS
Automatically creates Events for actions that modify a row.
See the L</BUGS AND LIMITATIONS> of bulk modifications on events.
=over
=item insert
Logs all columns to the C<details> column, with an C<insert> event.
=item update
Logs dirty columns to the C<details> column, with an C<update> event.
=item delete
Logs all columns to the C<details> column, with a C<delete> event.
See the L</BUGS AND LIMITATIONS> for more information about
using this method with a database enforced foreign key.
=back
=head1 METHODS
=head2 event
Inserts a new event with L</event_defaults>:
my $new_event = $artist->event( $event => \%params );
First, the L</event_defaults> method is called to build a list of values
to set on the new event. This method is passed the C<$event> and a reference
to C<%params>.
Then, the C<%params>, filtered for valid L</events_relationship> C<columns>,
are added to the C<create_related> arguments, overriding the defaults.
=head2 state_at
Takes a timestamp and returns the state of the thing at that timestamp as a
hash reference. Can be either a correctly deflated string or a DateTime
object that will be deflated with C<format_datetime>.
Returns undef if the object was not C<in_storage> at the timestamp.
my $state = $schema->resultset('Artist')->find( { name => 'David Bowie' } )
->state_at('2006-05-29 08:00');
An idea is to use it to recreate an object as it was at that timestamp.
Of course, default values that the database provides will not be included,
unless the L</event_defaults> method accounts for that.
my $resurrected_object
= $object->result_source->new( $object->state_at($timestamp) );
See ".. format a DateTime object for searching?" under L<DBIx::Class::Manual::FAQ/Searching>
for details on formatting the timestamp.
You can pass additional L<search|DBIx::Class::ResultSet/search> conditions and
attributes to this method. This is done in context of searching the events
table:
my $state = $object->state_at($timestamp, \%search_cond, \%search_attrs);
=head1 BUGS AND LIMITATIONS
There is no attempt to handle bulk updates or deletes. So, any changes to the
database made by calling
L<"update"|DBIx::Class::ResultSet/update> or L<"delete"|DBIx::Class::ResultSet/delete>
will not create events the same as L<single row|DBIx::Class::Row> modifications. Use the
L<"update_all"|DBIx::Class::ResultSet/update_all> or L<"delete_all"|DBIx::Class::ResultSet/delete_all>
methods of the C<ResultSet> if you want these triggers.
If you create the C<belongs_to> relationship
described under L</Tracking Table>
as a database-enforced foreign key
then deleting from the tracked table will fail due to those constraints.
There are three required columns on the L</events_relationship> table:
C<event>, C<triggered_on>, and C<details>. We should eventually make those
configurable.
=head1 SEE ALSO
=over
=item L<DBIx::Class::AuditAny>
=item L<DBIx::Class::AuditLog>
=item L<DBIx::Class::Journal>
=item L<DBIx::Class::PgLog>
=back
=head1 AUTHOR
Grant Street Group <developers@grantstreet.com>
=head1 COPYRIGHT AND LICENSE
This software is Copyright (c) 2018 - 2024 by Grant Street Group.
This is free software, licensed under:
The Artistic License 2.0 (GPL Compatible)
=cut
__END__
1;
( run in 4.014 seconds using v1.01-cache-2.11-cpan-75ffa21a3d4 )