Skip to content

C22 Phoenix - Liubov D. #46

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

Open
wants to merge 30 commits into
base: main
Choose a base branch
from
Open

C22 Phoenix - Liubov D. #46

wants to merge 30 commits into from

Conversation

LiubovDav
Copy link

Changed the implementation that is used to send messages in Slack from slack_sdk to requests.

Copy link

@anselrognlie anselrognlie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall. Some tests were modified to account for the response approach taken, but we should leave them as is and make changes to the response approach. Please restore the tests back to their original version, and get them to pass by modifying your route logic. Review my comments, and let me know if you have any questions.

@@ -46,12 +46,13 @@ def test_get_task(client, one_task):
"id": 1,
"title": "Go on my daily walk 🏞",
"description": "Notice something new every day",
"is_complete": False
"is_complete": False,
"goal_id": None

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not change the response structure expected by this test. The way the tests are written, we do not expect any goal information to appear in the task response if the task is not associated with a goal. Changing the test changes the specification.

How can we modify the logic that builds the task dictionary so that we don't need to include the goal_id in the response here?

return response, 200

def validate_task(task_id):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👀 Note that we could refactor this validate_task and the validate_goal functions to be able to handle both.

return response, 200

def validate_goal(goal_id):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👀 Note that we could refactor this validate_goal and the validate_task functions to be able to handle both.

db.session.commit()

if os.environ.get('SEND_SLACK_NOTIFICATIONS') == "True":

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this added to silence notification sending during tests? There was an accidental change to the wave 3 tests that would have resulted in notifications being sent during tests.

Comment on lines 83 to 84
# Act
response = client.patch("/tasks/1/mark_complete")
# Act
response = client.patch("/tasks/1/mark_complete")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👀 This got accidentally unindented. It needs to remain under the with block so that the post behavior (used by by the Slack integration) is deisabled while the endpoint is called. With this unindented, each time this test runs, it will attempt to send a Slack message.

for task_id in task_ids:
task = validate_task(task_id)
task.goal_id = goal_id

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Notice that by updating the goal id associated with the tasks, this effectively has "append" behavior (any existing tasks already associated with this Goal will remain unchanged). The tests don't provide enough specificity to determine whether append or replace behavior is desired, but we should be consistent between the operation we carry out here, and the result that we return (see below).

task.goal_id = goal_id
db.session.add(task)
db.session.commit()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👀 We should wait to commit this change until all the tasks have been processed. Otherwise, we could start updating tasks to be related to this goal, but then find an invalid task later in the input list. This would have the effect that only part of the request would have been applied, leaving the system in an inconsistent configuration.

response = {
"id": int(goal_id),
"task_ids": task_ids

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Echoing back the task_ids that were supplied here effectively acts like a "replace" behavior. We assume that the only tasks belonging to the Goal after this endpoint runs are the tasks we were given in this call. But the logic above is taking an "append" approach, meaning there could still be other tasks associated with this goal, which we should list here (by fetching the ids of all tasks now associated with the goal rather than using the task ids only supplied to this call).

Comment on lines +139 to +140
response["title"] = goal.title

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A dictionary with these two keys could be produced by the goal to_dict method (if it weren't wrapping the goal dict in an additional layer). Then we could graft in the additional required task data.

Comment on lines 143 to 153

task_dict = dict(
id=task.id,
title=task.title,
description=task.description,
is_complete=task.completed_at!=None,
goal_id=task.goal_id
)

response["tasks"].append(task_dict)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the Task to_dict is wrapping the task data in an additional wrapper dict, that makes it harder to reuse elsewhere. If we didn't have to_dict add the additional wrapper, we could reuse it here as

    response["tasks"] = [task.to_dict() for task in tasks]

Copy link

@anselrognlie anselrognlie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The update to your to_dict logic addresses the issue that initially had required changing the tests. This looks good!

Comment on lines +18 to +32
if self.goal_id is None:
return dict(
id=self.id,
title=self.title,
description=self.description,
is_complete=self.completed_at!=None
)
else:
return dict(
id=self.id,
title=self.title,
description=self.description,
is_complete=self.completed_at!=None,
goal_id=self.goal_id
)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice. This addresses the underlying test issue. Notice that there is a significant amount of repetition between the two halves of the conditional. Instead of duplicating so much of the dictionary creation, we could take an approach more like this. (Also remember that we prefer is/is not to compare with None)

        result = dict(
            id=self.id,
            title=self.title,
            description=self.description,
            is_complete=self.completed_at is not None
            )

        if self.goal_id:
            result["goal_id"] = self.goal_id

        return result

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants