Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First pass #1

Merged
merged 4 commits into from
Oct 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion MANIFEST
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ lib/TPS/Questionnaire/Schema/Result/QuestionnaireAnswer.pm
lib/TPS/Questionnaire/Schema/Result/QuestionnaireQuestion.pm
lib/TPS/Questionnaire/View/JSON.pm
Makefile.PL
MANIFEST This list of files
MANIFEST
META.yml
questionnaire.conf
questionnaire.psgi
Expand Down
61 changes: 61 additions & 0 deletions lib/TPS/Questionnaire/Controller/API.pm
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,67 @@ sub get_questionnaire :Path('questionnaire') GET CaptureArgs(1) {
}


=head2 put_questionnaire

Handles PUT action to /api/questionnaire/{id}

The ID is required, this is an "update" action to edit existing data on an unpublished questionnaire.
That is, you can edit the title (and in the future, the questions) associated with an unpublished questionnaire,
or you can publish a questionnaire.

Once a questionnaire is published it can accept responses, but none of its questions or metadata can be further modified.

Once published, a questionnaire cannot be unpublished. (In the future, we may want to be able to unpublish a
questionnaire. For example, if you want to revise an existing questionnaire, you'd publish a revised version and
unpublish the old version. But this would have to be done in such a way that no previously published questionnaires
could be modified. Previous responses to old questionnaires would be preserved.)

=cut

sub put_questionnaire :Path('questionnaire') PUT CaptureArgs(1) Consumes(JSON) {
my ($self, $c, $id) = (shift, @_);

## input validation?
## a. is the id valid, i.e., does it exist in the DB
## b. is this item (id) in an unpublished state?
##
my (%posted, $q, $qa, );

# %posted = %{$c->request->body_data};

if ($id) {
$q = TPS::Questionnaire::Model::Questionnaire->from_id($c->schema, $id);

if ( $q->is_published() ) {
$c->stash->{'status'} = 'error';
$c->stash->{'error'} = 'Not allowed to update an already published questionnaire.';
$c->response->status(400);
}
else {
$q = 'TPS::Questionnaire::Model::Questionnaire'->from_hashref($c->request->body_data);
$q->id( $id );
$q->update($c->schema);

$c->stash->{'status'} = 'ok';
$c->stash->{'result'} = $q->to_hashref;
$c->forward('View::JSON');
}
}
else {
## if $id not provided, should we do a "create" like POST does?
##
my $q = 'TPS::Questionnaire::Model::Questionnaire'->from_hashref($c->request->body_data);
$q->save($c->schema);
$c->stash->{'status'} = 'ok';
$c->stash->{'result'} = $q->to_hashref;
$c->forward('View::JSON');
}

}# end put_questionnaire




__PACKAGE__->meta->make_immutable;

1;
47 changes: 47 additions & 0 deletions lib/TPS/Questionnaire/Model/Questionnaire.pm
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,53 @@ sub summary_list {
}



=head2 update($schema)

Based on save, but expects that the ID exists.

Saves the questionnaire (title and is_published) using this object's ID.

Future improvement is to also save the associated questions to the database.

=cut

sub update {
my ($self, $schema) = (shift, @_);

# Even though this object has 'rw' attributes, questionnaires are
# conceptually write-once. or not.
unless ($self->has_id) {
croak 'Updating questionnaire requires that one already exists', $self;
return;
}

my $input = {
title => $self->title,
is_published => $self->is_published,
};


my $result = $schema
->resultset('Questionnaire')
->search( {questionnaire_id => $self->id} )
->update( $input );


## updated: 21 Oct 2021 by SJS
## comment: update() works above. need to update() the questions? am I into scope creep, yes. maybe.
## so the method works for the Questionnaire, and does allow changes to the two fields, and
## overall, only works for existing Qs. But it does not save/update the list of questions, which
## really bugs me. But I've run out of development time. bummer.
# my $rank = 0;
# for my $q (@{$self->questions}) {
# $q->_save($self, ++$rank, @_);
# }

return $self->id;
}


__PACKAGE__->meta->make_immutable;

1;
132 changes: 132 additions & 0 deletions t/unit/TPS/Questionnaire/Model/Questionnaire.t
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,138 @@ tests save => sub {
) or diag explain($object);
};


=begin comment

Step 1.
Manual test plan using POSTMAN:
do a GET to know active Q's.
do a PUT w/o ID to create new record:

```
{
"title": "Steve Test PUT without id",
"is_published": false,
"questions": [
{
"question_type": "text",
"question_text": "New question here, does not have an id."
}
]
}
```

get a 200 status ok

Step 2.
In Pycharm (or other database tool) verify that the new Q was created. Since we are NOT dealing with
questions in the PUT, their presence in the submitted data is optional. We could use POST to create a
new Q (that would include the questions), being sure to set the is_published to 'false'. But, the
result does not include the QID, so there's no real difference.

Step 3.
Back to POSTMAN, update the url to include the QID created above.
do a PUT w/ID to update the record with:

```
{
"title": "Steve Test PUT with id",
"is_published": true,
}
```

get a 200 status ok

verify in database that the id_published changes from false to true (0 to 1).
verify with GET that the Q is listed.

Step 4.
Back to POSTMAN, send the same data to the same URL as in Step 3.

get a 400 status error

This verifies that the PUT will not update a published Questionnaire.
end.

=end comment

=cut

## updated: 21 Oct 2021 by SJS
## comment: first pass at testing the put method. Need to save hash, but then find the QID, not from GET.
##

tests update => sub {
plan(2);

my $object = $CLASS->from_hashref({
title => 'Steve Test',
is_published => 0,
questions => [
{
question_type => 'text',
question_text => 'New Question without id.'
}
],
});

require TPS::Questionnaire::Schema;
my $schema = TPS::Questionnaire::Schema->connect(
sub { make_database('schema.sql') },
);

# Save and reload from database
my $id = $object->save($schema);
$object = $CLASS->from_id($schema, $id);

is(
$object,
object {
prop 'isa' => 'TPS::Questionnaire::Model::Questionnaire';
call 'title' => string 'Steve Test';
call 'is_published' => bool !!0;
call 'questions' => array {
item object {
prop 'isa' => 'TPS::Questionnaire::Model::Question::Text';
call 'question_text' => 'New Question without id.';
};

end();
};
},
'Correct object loaded from database',
) or diag explain($object);

# update the saved object
#
$object->is_published( 1 );
my $up_id = $object->update($schema);
$object = $CLASS->from_id($schema, $up_id);

is(
$object,
object {
prop 'isa' => 'TPS::Questionnaire::Model::Questionnaire';
call 'title' => string 'Steve Test';
call 'is_published' => bool !!1;
call 'questions' => array {
item object {
prop 'isa' => 'TPS::Questionnaire::Model::Question::Text';
call 'question_text' => 'New Question without id.';
};

end();
};
},
'Updated the object properly',
)
or diag explain($object);
};





done_testing();

1;