Skip to content

Commit 74355a3

Browse files
Merge pull request #837 from JarriqTheTechie/feature/find_or
Feature/find_or
2 parents c01e632 + 541a8c7 commit 74355a3

File tree

4 files changed

+48
-2
lines changed

4 files changed

+48
-2
lines changed

src/masoniteorm/exceptions.py

+4
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,7 @@ class InvalidUrlConfiguration(Exception):
3232

3333
class MultipleRecordsFound(Exception):
3434
pass
35+
36+
37+
class InvalidArgument(Exception):
38+
pass

src/masoniteorm/models/Model.py

+1
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ class Model(TimeStampsMixin, ObservesEvents, metaclass=ModelMeta):
183183
"doesnt_exist",
184184
"doesnt_have",
185185
"exists",
186+
"find_or",
186187
"find_or_404",
187188
"find_or_fail",
188189
"first_or_fail",

src/masoniteorm/query/QueryBuilder.py

+26-2
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import inspect
22
from copy import deepcopy
33
from datetime import datetime
4-
from typing import Any, Dict, List, Optional
4+
from typing import Any, Dict, List, Optional, Callable
55

66
from ..collection.Collection import Collection
77
from ..config import load_config
88
from ..exceptions import (
99
HTTP404,
1010
ConnectionNotRegistered,
1111
ModelNotFound,
12-
MultipleRecordsFound,
12+
MultipleRecordsFound, InvalidArgument,
1313
)
1414
from ..expressions.expressions import (
1515
AggregateExpression,
@@ -1797,6 +1797,30 @@ def find(self, record_id):
17971797

17981798
return self.where(self._model.get_primary_key(), record_id).first()
17991799

1800+
def find_or(self, record_id: int, callback: Callable, args=None):
1801+
"""Finds a row by the primary key ID (Requires a model) or raise a ModelNotFound exception.
1802+
1803+
Arguments:
1804+
record_id {int} -- The ID of the primary key to fetch.
1805+
callback {Callable} -- The function to call if no record is found.
1806+
1807+
Returns:
1808+
Model|Callable
1809+
"""
1810+
1811+
if not callable(callback):
1812+
raise InvalidArgument("A callback must be callable.")
1813+
1814+
result = self.find(record_id=record_id)
1815+
1816+
if not result:
1817+
if not args:
1818+
return callback()
1819+
else:
1820+
return callback(*args)
1821+
1822+
return result
1823+
18001824
def find_or_fail(self, record_id):
18011825
"""Finds a row by the primary key ID (Requires a model) or raise a ModelNotFound exception.
18021826

tests/sqlite/models/test_sqlite_model.py

+17
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,23 @@ def test_can_find_list(self):
8282
sql, """SELECT * FROM "users" WHERE "users"."id" IN ('1','2','3')"""
8383
)
8484

85+
def test_find_or_if_record_not_found(self):
86+
# Insane record number so record cannot be found
87+
record_id = 1_000_000_000_000_000
88+
89+
result = User.find_or(record_id, lambda: "Record not found.")
90+
self.assertEqual(
91+
result, "Record not found."
92+
)
93+
94+
def test_find_or_if_record_found(self):
95+
record_id = 1
96+
result_id = User.find_or(record_id, lambda: "Record not found.").id
97+
98+
self.assertEqual(
99+
result_id, record_id
100+
)
101+
85102
def test_can_set_and_retreive_attribute(self):
86103
user = User.hydrate({"id": 1, "name": "joe", "customer_id": 1})
87104
user.customer_id = "CUST1"

0 commit comments

Comments
 (0)