feat: add SQLAlchemy models for Category, CategoryWord, Game, Word
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
2930adb51d
commit
041b768cd4
@@ -0,0 +1,5 @@
|
|||||||
|
from sqlalchemy.orm import DeclarativeBase
|
||||||
|
|
||||||
|
|
||||||
|
class Base(DeclarativeBase):
|
||||||
|
pass
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
from sqlalchemy import Column, ForeignKey, Integer, String, UniqueConstraint
|
||||||
|
from sqlalchemy.orm import relationship
|
||||||
|
|
||||||
|
from models import Base
|
||||||
|
|
||||||
|
|
||||||
|
class Category(Base):
|
||||||
|
__tablename__ = "categories"
|
||||||
|
|
||||||
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||||
|
name = Column(String(50), unique=True, nullable=False)
|
||||||
|
|
||||||
|
words = relationship("CategoryWord", back_populates="category")
|
||||||
|
|
||||||
|
|
||||||
|
class CategoryWord(Base):
|
||||||
|
__tablename__ = "category_words"
|
||||||
|
__table_args__ = (UniqueConstraint("category_id", "word"),)
|
||||||
|
|
||||||
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||||
|
category_id = Column(Integer, ForeignKey("categories.id"), nullable=False)
|
||||||
|
word = Column(String(20), nullable=False)
|
||||||
|
|
||||||
|
category = relationship("Category", back_populates="words")
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
import uuid
|
||||||
|
from datetime import datetime, timezone
|
||||||
|
|
||||||
|
from sqlalchemy import (
|
||||||
|
Boolean,
|
||||||
|
Column,
|
||||||
|
DateTime,
|
||||||
|
ForeignKey,
|
||||||
|
Integer,
|
||||||
|
String,
|
||||||
|
)
|
||||||
|
from sqlalchemy.orm import relationship
|
||||||
|
from sqlalchemy.types import JSON
|
||||||
|
|
||||||
|
from models import Base
|
||||||
|
|
||||||
|
|
||||||
|
class Game(Base):
|
||||||
|
__tablename__ = "games"
|
||||||
|
|
||||||
|
id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
|
||||||
|
category_id = Column(Integer, ForeignKey("categories.id"), nullable=False)
|
||||||
|
board_size = Column(Integer, nullable=False, default=10)
|
||||||
|
grid = Column(JSON, nullable=False)
|
||||||
|
status = Column(String(20), nullable=False, default="in_progress")
|
||||||
|
started_at = Column(
|
||||||
|
DateTime, nullable=False, default=lambda: datetime.now(timezone.utc)
|
||||||
|
)
|
||||||
|
completed_at = Column(DateTime, nullable=True)
|
||||||
|
|
||||||
|
category = relationship("Category")
|
||||||
|
words = relationship("Word", back_populates="game")
|
||||||
|
|
||||||
|
|
||||||
|
class Word(Base):
|
||||||
|
__tablename__ = "words"
|
||||||
|
|
||||||
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||||
|
game_id = Column(String(36), ForeignKey("games.id"), nullable=False)
|
||||||
|
text = Column(String(20), nullable=False)
|
||||||
|
start_row = Column(Integer, nullable=False)
|
||||||
|
start_col = Column(Integer, nullable=False)
|
||||||
|
direction = Column(String(2), nullable=False)
|
||||||
|
found = Column(Boolean, nullable=False, default=False)
|
||||||
|
found_at = Column(DateTime, nullable=True)
|
||||||
|
|
||||||
|
game = relationship("Game", back_populates="words")
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import pytest
|
||||||
|
from sqlalchemy import create_engine
|
||||||
|
from sqlalchemy.orm import sessionmaker
|
||||||
|
|
||||||
|
from models import Base
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def db_session():
|
||||||
|
engine = create_engine("sqlite:///:memory:")
|
||||||
|
Base.metadata.create_all(engine)
|
||||||
|
Session = sessionmaker(bind=engine)
|
||||||
|
session = Session()
|
||||||
|
yield session
|
||||||
|
session.close()
|
||||||
|
engine.dispose()
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
from models.category import Category, CategoryWord
|
||||||
|
from models.game import Game, Word
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_category(db_session):
|
||||||
|
cat = Category(name="animals")
|
||||||
|
db_session.add(cat)
|
||||||
|
db_session.commit()
|
||||||
|
assert cat.id is not None
|
||||||
|
assert cat.name == "animals"
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_category_word(db_session):
|
||||||
|
cat = Category(name="animals")
|
||||||
|
db_session.add(cat)
|
||||||
|
db_session.flush()
|
||||||
|
word = CategoryWord(category_id=cat.id, word="TIGER")
|
||||||
|
db_session.add(word)
|
||||||
|
db_session.commit()
|
||||||
|
assert word.category_id == cat.id
|
||||||
|
assert word.word == "TIGER"
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_game(db_session):
|
||||||
|
cat = Category(name="animals")
|
||||||
|
db_session.add(cat)
|
||||||
|
db_session.flush()
|
||||||
|
game = Game(
|
||||||
|
category_id=cat.id,
|
||||||
|
board_size=10,
|
||||||
|
grid=[["A"] * 10 for _ in range(10)],
|
||||||
|
)
|
||||||
|
db_session.add(game)
|
||||||
|
db_session.commit()
|
||||||
|
assert game.id is not None
|
||||||
|
assert len(game.id) == 36 # UUID
|
||||||
|
assert game.status == "in_progress"
|
||||||
|
assert game.started_at is not None
|
||||||
|
assert game.completed_at is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_word(db_session):
|
||||||
|
cat = Category(name="animals")
|
||||||
|
db_session.add(cat)
|
||||||
|
db_session.flush()
|
||||||
|
game = Game(category_id=cat.id, board_size=10, grid=[])
|
||||||
|
db_session.add(game)
|
||||||
|
db_session.flush()
|
||||||
|
word = Word(
|
||||||
|
game_id=game.id,
|
||||||
|
text="TIGER",
|
||||||
|
start_row=0,
|
||||||
|
start_col=0,
|
||||||
|
direction="E",
|
||||||
|
)
|
||||||
|
db_session.add(word)
|
||||||
|
db_session.commit()
|
||||||
|
assert word.found is False
|
||||||
|
assert word.found_at is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_game_words_relationship(db_session):
|
||||||
|
cat = Category(name="animals")
|
||||||
|
db_session.add(cat)
|
||||||
|
db_session.flush()
|
||||||
|
game = Game(category_id=cat.id, board_size=10, grid=[])
|
||||||
|
db_session.add(game)
|
||||||
|
db_session.flush()
|
||||||
|
w1 = Word(game_id=game.id, text="TIGER", start_row=0, start_col=0, direction="E")
|
||||||
|
w2 = Word(game_id=game.id, text="LION", start_row=1, start_col=0, direction="S")
|
||||||
|
db_session.add_all([w1, w2])
|
||||||
|
db_session.commit()
|
||||||
|
db_session.refresh(game)
|
||||||
|
assert len(game.words) == 2
|
||||||
Reference in New Issue
Block a user