1 package Reaction::UI::Controller::Collection::CRUD;
5 use base 'Reaction::UI::Controller::Collection';
8 use aliased 'Reaction::UI::ViewPort::Action';
9 use aliased 'Reaction::UI::ViewPort::ListView';
11 sub _build_action_viewport_map {
13 my $map = $self->next::method(@_);
14 $map->{list} = ListView if exists $map->{list};
16 #my %allowed = map { $_ => undef }
17 # ( @{$self->default_member_actions}, @{$self->default_collection_actions} );
18 my @local_actions = qw/create update delete delete_all/;
19 #$map->{$_} = Action for grep { exists $allowed{$_} } @local_actions;
21 $map->{$_} = Action for @local_actions;
25 sub _build_default_member_actions {
26 [ @{shift->next::method(@_)}, qw/update delete/ ];
29 sub _build_default_collection_actions {
30 [ @{shift->next::method(@_)}, qw/create delete_all/ ];
33 sub get_model_action {
34 my ($self, $c, $name, $target) = @_;
35 return $target->action_for($name, ctx => $c);
37 sub create :Chained('base') :PathPart('create') :Args(0) {
39 my $apply = sub { $self->after_create_callback( @_) };
40 my $close = sub { $self->on_create_close_callback( @_) };
42 target => ($c->stash->{collection} || $self->get_collection($c)),
43 on_apply_callback => $self->make_context_closure($apply),
44 on_close_callback => $self->make_context_closure($close),
46 $self->basic_model_action( $c, $vp_args);
49 sub delete_all :Chained('base') :PathPart('delete_all') :Args(0) {
51 my $close = sub { $self->on_delete_all_close_callback( @_) };
52 $self->basic_model_action( $c, {
53 target => ($c->stash->{collection} || $self->get_collection($c)),
54 on_close_callback => $self->make_context_closure($close),
58 sub on_delete_all_close_callback {
60 $self->redirect_to($c, 'list');
63 sub after_create_callback {
64 my ($self, $c, $vp, $result) = @_;
65 return $self->redirect_to
66 ( $c, 'update', [ @{$c->req->captures}, $result->id ] );
69 sub on_create_close_callback {
70 my($self, $c, $vp) = @_;
71 $self->redirect_to( $c, 'list' );
74 sub update :Chained('object') :Args(0) {
76 my $close = sub { $self->on_update_close_callback( @_) };
78 on_close_callback => $self->make_context_closure($close),
80 $self->basic_model_action( $c, $vp_args);
83 sub on_update_close_callback {
85 #this needs a better solution. currently thinking about it
86 my @cap = @{$c->req->captures};
87 pop(@cap); # object id
88 $self->redirect_to($c, 'list', \@cap);
91 sub delete :Chained('object') :Args(0) {
93 my $close = sub { $self->on_delete_close_callback( @_) };
95 on_close_callback => $self->make_context_closure($close),
97 $self->basic_model_action( $c, $vp_args);
100 sub on_delete_close_callback {
102 #this needs a better solution. currently thinking about it
103 my @cap = @{$c->req->captures};
104 pop(@cap); # object id
105 $self->redirect_to($c, 'list', \@cap);
108 sub basic_model_action {
109 my ($self, $c, $vp_args) = @_;
110 my $stash = $c->stash;
111 my $target = delete $vp_args->{target};
112 $target ||= ($stash->{object} || $stash->{collection} || $self->get_collection($c));
114 my $action_name = join('', map{ ucfirst } split('_', $c->stack->[-1]->name));
115 my $model = $self->get_model_action($c, $action_name, $target);
116 return $self->basic_page($c, { model => $model, %{$vp_args||{}} });
125 Reaction::UI::Controller::Collection::CRUD - Basic CRUD functionality for Reaction::InterfaceModel data
129 Controller class which extends L<Reaction::UI::Controller::Collection> to
130 provide basic Create / Update / Delete / DeleteAll actions.
132 Building on the base of the Collection controller this controller allows you to
133 easily create complex and highly flexible CRUD functionality for your
134 InterfaceModel models by providing a simple way to render and process your
135 custom InterfaceModel Actions and customize built-ins.
139 =head2 get_model_action $c, $action_name, $target_im
141 Get an instance of the C<$action_name>
142 L<InterfaceModel::Action|Reaction::InterfaceModel::Action> for model C<$target>
143 This action is suitable for passing to an
144 C<Action|Reaction::UI::ViewPort::Action> viewport
146 =head2 after_create_callback $c, $vp, $result
148 When a <create> action is applied, move the user to the new object's,
151 =head2 basic_model_action $c, \%vp_args
153 Extension to C<basic_page> which automatically instantiates an
154 L<InterfaceModel::Action|Reaction::InterfaceModel::Action> with the right
155 data target using C<get_model_action>
157 =head2 _build_action_viewport_map
159 Map C<create>, C<update>, C<delete> and C<delete_all> to use the
160 L<Action|Reaction::UI::ViewPort::Action> viewport by default and have C<list>
161 use L<ListView|Reaction::UI::ViewPort::ListView> by default.
163 =head2 _build_default_member_actions
165 Add C<update> and C<delete> to the list of default actions.
167 =head2 _build_default_collection_actions
169 Add C<create> and C<delete_all> to the list of default actions.
175 Chaned to C<base>. Create a new member of the collection represented by
176 this controller. By default it attaches the C<after_create_callback> to
177 DWIM after apply operations.
179 See L<Create|Reaction::InterfaceModel::Action::DBIC::ResultSet::Create>
184 Chained to B<base>, delete all the members of the B<collection>. In most cases
185 this is very much like a C<TRUNCATE> operation.
187 See L<DeleteAll|Reaction::InterfaceModel::Action::DBIC::ResultSet::DeleteAll>
192 Chained to C<object>, update a single object.
194 See L<Update|Reaction::InterfaceModel::Action::DBIC::Result::Update>
199 Chained to C<object>, delete a single object.
201 See L<Delete|Reaction::InterfaceModel::Action::DBIC::Result::Delete>
206 L<Reaction::UI::Controller::Collection>, L<Reaction::UI::Controller>
210 See L<Reaction::Class> for authors.
214 See L<Reaction::Class> for the license.