Skip to content
This repository has been archived by the owner on Sep 2, 2021. It is now read-only.

Commit

Permalink
added new find methods
Browse files Browse the repository at this point in the history
  • Loading branch information
Brian Muller committed May 22, 2012
1 parent 6245738 commit c239dd8
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 2 deletions.
30 changes: 29 additions & 1 deletion twistar/dbobject.py
Expand Up @@ -8,7 +8,7 @@
from twistar.registry import Registry
from twistar.relationships import Relationship
from twistar.exceptions import InvalidRelationshipError, DBObjectSaveError, ReferenceNotSavedError
from twistar.utils import createInstances, deferredDict
from twistar.utils import createInstances, deferredDict, dictToWhere
from twistar.validation import Validator, Errors

from BermiInflector.Inflector import Inflector
Expand Down Expand Up @@ -364,6 +364,34 @@ class name.
return klass.TABLENAME


@classmethod
def findOrCreate(klass, **attrs):
"""
Find all instances of a given class based on the attributes given (just like C{findBy}).
If a match isn't found, create a new instance and return that.
"""
def handle(result):
if len(result) == 0:
return klass(**attrs).save()
return result[0]
return klass.findBy(**attrs).addCallback(handle)


@classmethod
def findBy(klass, **attrs):
"""
Find all instances of the given class based on an exact match of attributes.
For instance:
C{User.find(first_name='Bob', last_name='Smith')}
Will return all matches.
"""
where = dictToWhere(attrs)
return klass.find(where = where)


@classmethod
def find(klass, id=None, where=None, group=None, limit=None, orderby=None):
"""
Expand Down
30 changes: 30 additions & 0 deletions twistar/tests/test_dbobject.py
Expand Up @@ -22,6 +22,36 @@ def tearDown(self):
yield tearDownDB(self)


@inlineCallbacks
def test_findBy(self):
r = yield User.findBy(first_name="Non", last_name="Existant")
self.assertEqual(r, [])

r = yield User.findBy(first_name="First", last_name="Last", age=11)
self.assertEqual(r, [])

r = yield User.findBy(first_name="First", last_name="Last", age=10)
self.assertEqual(r[0], self.user)

r = yield User.findBy(first_name="First", last_name="Last")
self.assertEqual(r[0], self.user)

u = yield User(first_name="Bob").save()
r = yield User.findBy()
self.assertEqual(len(r), 2)


@inlineCallbacks
def test_findOrCreate(self):
# make sure we didn't create a new user
r = yield User.findOrCreate(first_name="First")
self.assertEqual(r.id, self.user.id)

# make sure we do create a new user
r = yield User.findOrCreate(first_name="First", last_name="Non")
self.assertTrue(r.id != self.user.id)


@inlineCallbacks
def test_creation(self):
# test creating blank object
Expand Down
18 changes: 17 additions & 1 deletion twistar/utils.py
Expand Up @@ -27,7 +27,23 @@ def createInstances(props, klass):

return defer.succeed(None)



def dictToWhere(attrs, joiner="AND"):
"""
Convert a dictionary of attribute: value to a where statement.
For instance, dictToWhere({'one': 'two', 'three': 'four'}) returns:
['(one = ?) AND (three = ?)', 'two', 'four']
@return: Expression above if len(attrs) > 0, None otherwise
"""
if len(attrs) == 0:
return None

wheres = map(lambda name: "(%s = ?)" % name, attrs.keys())
return [(" %s " % joiner).join(wheres)] + attrs.values()


def joinWheres(wone, wtwo, joiner="AND"):
"""
Take two wheres (of the same format as the C{where} parameter in the function
Expand Down

0 comments on commit c239dd8

Please sign in to comment.