Commit | Line | Data |
7bde9079 |
1 | package DBIx::Class::UserStamp; |
2 | |
3 | use base qw(DBIx::Class); |
4 | |
5 | use warnings; |
6 | use strict; |
7 | |
8 | our $VERSION = '0.10'; |
9 | |
10 | __PACKAGE__->mk_classdata( |
11 | '__column_userstamp_triggers' => { |
12 | on_update => [], on_create => [] |
13 | } |
14 | ); |
15 | |
16 | =head1 NAME |
17 | |
18 | DBIx::Class::UserStamp - Automatically set update and create user id fields |
19 | |
20 | =head1 DESCRIPTION |
21 | |
22 | Automatically set fields on 'update' and 'create' that hold user id |
23 | values in a table. This can be used for any user id based |
24 | field that needs trigger like functionality when a record is |
25 | added or updated. |
26 | |
27 | =head1 SYNOPSIS |
28 | |
29 | package MyApp::Schema; |
30 | |
31 | __PACKAGE__->mk_group_accessors('simple' => qw/current_user_id/); |
32 | |
33 | |
34 | package MyApp::Model::MyAppDB; |
35 | use Moose; |
36 | |
37 | around 'build_per_context_instance' => sub { |
38 | my ($meth, $self) = (shift, shift); |
39 | my ($c) = @_; # There are other params but we dont care about them |
40 | my $new = bless({ %$self }, ref($self)); |
41 | my $user_info = $c->_user_in_session; |
42 | my $user = $new->schema->resultset('User')->new_result({ %$user_info }); |
43 | $new->schema->current_user_id($user->id) if (defined $user_info); |
44 | return $new; |
45 | }; |
46 | |
47 | |
48 | package MyApp::Schema::SomeTable; |
49 | |
50 | __PACKAGE__->load_components(qw( UserStamp ... Core )); |
51 | |
52 | __PACKAGE__->add_columns( |
53 | id => { data_type => 'integer' }, |
54 | u_created => { data_type => 'int', store_user_on_create => 1 }, |
55 | u_updated => { data_type => 'int', |
56 | store_user_on_create => 1, store_user_on_update => 1 }, |
57 | ); |
58 | |
59 | Now, any update or create actions will update the specified columns with the |
60 | current user_id, using the current_user_id accessor. |
61 | |
62 | This is effectively trigger emulation to ease user id field insertion |
63 | |
64 | =cut |
65 | |
66 | sub add_columns { |
67 | my $self = shift; |
68 | |
69 | # Add everything else, get everything setup, and then process |
70 | $self->next::method(@_); |
71 | |
72 | my @update_columns = (); |
73 | my @create_columns = (); |
74 | |
75 | foreach my $column ( $self->columns ) { |
76 | my $info = $self->column_info($column); |
77 | if ( $info->{store_user_on_update} ) { |
78 | push @update_columns, $column; |
79 | } |
80 | if ( $info->{store_user_on_create} ) { |
81 | push @create_columns, $column; |
82 | } |
83 | } |
84 | if ( @update_columns or @create_columns ) { |
85 | my $triggers = { |
86 | on_update => [ @update_columns ], |
87 | on_create => [ @create_columns ], |
88 | }; |
89 | $self->__column_userstamp_triggers($triggers); |
90 | } |
91 | } |
92 | |
93 | sub insert { |
94 | my $self = shift; |
95 | my $attrs = shift; |
96 | |
97 | my $user_id = $self->get_current_user_id; |
98 | |
99 | my @columns = @{ $self->__column_userstamp_triggers()->{on_create} }; |
100 | |
101 | foreach my $column ( @columns ) { |
102 | next if defined $self->get_column( $column ); |
103 | my $accessor = $self->column_info($column)->{accessor} || $column; |
104 | $self->$accessor($user_id); |
105 | } |
106 | |
107 | return $self->next::method(@_); |
108 | } |
109 | |
110 | sub update { |
111 | my $self = shift; |
112 | |
113 | my $user_id = $self->get_current_user_id; |
114 | my %dirty = $self->get_dirty_columns(); |
115 | my @columns = @{ $self->__column_userstamp_triggers()->{on_update} }; |
116 | |
117 | foreach my $column ( @columns ) { |
118 | next if exists $dirty{ $column }; |
119 | my $accessor = $self->column_info($column)->{accessor} || $column; |
120 | $self->$accessor($user_id); |
121 | } |
122 | |
123 | return $self->next::method(@_); |
124 | } |
125 | |
126 | =head1 METHODS |
127 | |
128 | =head2 get_current_user_id |
129 | |
130 | This method is meant to be overridden. The default is to return a |
131 | schema accessor called current_user_id which should be populated as such. |
132 | |
133 | =cut |
134 | sub get_current_user_id { shift->result_source->schema->current_user_id } |
135 | |
136 | =head1 AUTHOR |
137 | |
138 | Matt S. Trout <mst@shadowcatsystems.co.uk> |
139 | |
140 | =head1 CONTRIBUTOR |
141 | |
142 | John Goulah <jgoulah@cpan.org> |
143 | |
144 | =head1 COPYRIGHT |
145 | |
146 | This program is free software; you can redistribute |
147 | it and/or modify it under the same terms as Perl itself. |
148 | |
149 | =cut |
150 | |
151 | 1; |