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

Sphinx-Weixi_He, Phoenix- Madina Dzhetegenova #67

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

Conversation

Madina-j
Copy link

No description provided.

@Madina-j Madina-j changed the title Ada C22 Phoenix Class_ Madina Dzhetegenova Sphinx-Weixi_He, Phoenix- Madina Dzhetegenova Oct 21, 2024
Copy link
Contributor

@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.

You're off to a good start. There are a few minor naming points to consider, and watch out for that default parameter in the Planet __init__ method, but otherwise you're right on track.

from flask import Blueprint, abort, make_response
from ..models.planet import planets

solar_system_bp = Blueprint("solar_system_bp", __name__, url_prefix="/planets")
Copy link
Contributor

Choose a reason for hiding this comment

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

Prefer to use the resource name (rather than the project name) as part of the blueprint name. So here, planets_bp, since this blueprint is related to the planets resources.

Copy link
Contributor

Choose a reason for hiding this comment

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

When moving the routes file into a folder (theoretically, to group multiple routes files together as we add additional resources), prefer to include the resource name as part of the file name. So here, something like planets_routes.py or planet_routes.py.

@@ -0,0 +1,19 @@

class Planet:
def __init__(self, id, name, description, flag= bool):
Copy link
Contributor

Choose a reason for hiding this comment

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

👀 The expression for the default would generally be a value of the desired type, rather than the type name itself.

    def __init__(self, id, name, description, flag=False):

As written, if we left of the flag value, then self.flag would be literally set to the bool type, not a boolean value (True/False).

Copy link
Contributor

Choose a reason for hiding this comment

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

It's not immediately obvious that the attrbiute called flag is intended to store a boolean. Consider a name like has_flag. Variables that start with words like is_ or has_ (depending on what makes grammatical sense) make it more clear that this is intended to hold a yes/no (boolean) value.

Comment on lines 13 to 14
Planet(3, "Earth", "The only planet known to support life.", True ),
Planet(4, "Mars", "Known as the Red Planet.", True ),
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: be careful of extra spaces.

    Planet(3, "Earth", "The only planet known to support life.", True), 
    Planet(4, "Mars", "Known as the Red Planet.", True), 

@@ -0,0 +1,42 @@
from flask import Blueprint, abort, make_response
from ..models.planet import planets
Copy link
Contributor

Choose a reason for hiding this comment

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

👍 Nice relative import.

Comment on lines 23 to 28
return{
"id":planet.id,
"name":planet.name,
"description":planet.description,
"flag":planet.flag
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: for dictionary literals, prefer spaces after the :

    return {
        "id": planet.id,
        "name": planet.name,
        "description": planet.description,
        "flag": planet.flag
    }

Comment on lines 10 to 15
results_list.append(dict(
id=planet.id,
name=planet.name,
description=planet.description,
flag=planet.flag
))
Copy link
Contributor

Choose a reason for hiding this comment

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

Even though this is using the dict() style and later (in get_one_planet) we use the {} style, notice how both are building the same dictionary structure from a planet record. Maybe we could make a helper function/method to DRY up our code.

Copy link
Contributor

@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.

Nice work making the modifications to connect your API to your database, expanding the endpoints, and adding some tests. Everything here should be able to be applied to your task list implementations.


def create_app():
def create_app(config=None):
Copy link
Contributor

Choose a reason for hiding this comment

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

👍 We need this param to accept the additional options for testing, but it needs to be defaulted since nothing will be passed in when starting with flask run

app = Flask(__name__)

app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SQLALCHEMY_DATABASE_URI'] = os.environ.get('SQLALCHEMY_DATABASE_URI')
Copy link
Contributor

Choose a reason for hiding this comment

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

👍 Loads the connection string from the environment (provided with our .env during development).


if config:
app.config.update(config)
db.init_app(app)
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: Leave a blank line between the end of the conditional block and this logic.

id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
name: Mapped[str]
description: Mapped[str]
flag:Mapped[bool]
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: Leave a space after the : in type expressions.

    flag: Mapped[bool]

self.name = name
self.description = description
self.flag = flag
class Planet(db.Model):
Copy link
Contributor

Choose a reason for hiding this comment

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

👍 Nice modifications to associate this model type with our database.

return app.test_client()

@pytest.fixture
def two_saved_planets(app):
Copy link
Contributor

Choose a reason for hiding this comment

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

👍 Nice test fixture adding two records.


db.session.add_all([planet_1, planet_2])

db.session.commit()
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider returning the list of records. The return value becomes the value passed in for the fixture in a test. By returning the records, we could use their ids in the dependent tests. While our approach of dropping and recreating the database for each test should guarantee that these records are ids 1 and 2, we could use the ids actually assigned by the database to remove that assumption.


def test_get_one_book_succeeds(client, two_saved_planets):
# Act
response = client.get("/planets/1")
Copy link
Contributor

Choose a reason for hiding this comment

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

If we returned the record list from the fixture, then we could write this line as

    response = client.get(f"/planets/{two_saved_planets[0].id}")

# Assert
assert response.status_code == 200
assert response_body == {
"id": 1,
Copy link
Contributor

Choose a reason for hiding this comment

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

If we returned the record list from the fixture, then we could check the id as

        "id": two_saved_planets[0].id,


def test_get_planet_by_id_returns_404(client):
response = client.get("/planets/1")
assert response.status_code == 404
Copy link
Contributor

Choose a reason for hiding this comment

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

👀 We should also check that the response body is the expected message.

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