Skip to content

Commit

Permalink
feat: enhance foreign key handling and add validation
Browse files Browse the repository at this point in the history
- Updated `foreign_key` method in `BaseModel` to accept additional keyword arguments for flexibility.
- Added null check handling in `TypeIDType` methods for improved robustness.
- Integrated relationships and foreign key handling in test cases, ensuring enhanced functionality and validation of models.

Generated-by: aiautocommit
  • Loading branch information
iloveitaly committed Jan 11, 2025
1 parent 92f632a commit 61d5849
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 3 deletions.
6 changes: 4 additions & 2 deletions activemodel/base_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,16 +145,18 @@ def __tablename__(cls) -> str:
return pydash.strings.snake_case(cls.__name__)

@classmethod
def foreign_key(cls):
def foreign_key(cls, **kwargs):
"""
Returns a Field object referencing the foreign key of the model.
"""

field_options = {"nullable": False} | kwargs

return Field(
# TODO id field is hard coded, should pick the PK field in case it's different
sa_type=cls.model_fields["id"].sa_column.type, # type: ignore
foreign_key=f"{cls.__tablename__}.id",
nullable=False,
**field_options,
)

@classmethod
Expand Down
6 changes: 6 additions & 0 deletions activemodel/types/typeid.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ def process_bind_param(self, value, dialect):
This is run when a search query is built or ...
"""

if value is None:
return None

if isinstance(value, UUID):
# then it's a UUID class, such as UUID('01942886-7afc-7129-8f57-db09137ed002')
return value
Expand All @@ -80,6 +83,9 @@ def process_bind_param(self, value, dialect):
raise ValueError("Unexpected input type")

def process_result_value(self, value, dialect):
if value is None:
return None

return TypeID.from_uuid(value, self.prefix)

# def coerce_compared_value(self, op, value):
Expand Down
16 changes: 15 additions & 1 deletion test/typeid_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

from activemodel import BaseModel
from activemodel.mixins import TypeIDMixin
from activemodel.types.typeid import TypeIDType
from sqlmodel import Relationship


def test_enforces_unique_prefixes():
Expand All @@ -25,10 +27,15 @@ def test_no_empty_prefixes_test():
TYPEID_PREFIX = "myid"


class ExampleWithId(BaseModel, TypeIDMixin(TYPEID_PREFIX), table=True):
class AnotherExample(BaseModel, TypeIDMixin("myotherid"), table=True):
pass


class ExampleWithId(BaseModel, TypeIDMixin(TYPEID_PREFIX), table=True):
another_example_id: TypeIDType = AnotherExample.foreign_key(nullable=True)
another_example: AnotherExample = Relationship()


def test_get_through_prefixed_uid():
type_uid = TypeID(prefix=TYPEID_PREFIX)

Expand Down Expand Up @@ -88,3 +95,10 @@ def test_render_typeid(create_and_wipe_database):
assert json.loads(wrapped_example.model_dump_json())["example"]["id"] == str(
example.id
)


def test_json_schema(create_and_wipe_database):
"json schema generation shouldn't be meaningfully different than json rendering, but let's check it anyway"

example = ExampleWithId().save()
example.model_json_schema()

0 comments on commit 61d5849

Please sign in to comment.