Permalink
Browse files

added new find methods

  • Loading branch information...
1 parent 6245738 commit c239dd87d2e22896ddfb53added58582bd207f72 @bmuller committed May 22, 2012
Showing with 76 additions and 2 deletions.
  1. +29 −1 twistar/dbobject.py
  2. +30 −0 twistar/tests/test_dbobject.py
  3. +17 −1 twistar/utils.py
View
@@ -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
@@ -365,6 +365,34 @@ class name.
@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):
"""
Find instances of a given class.
@@ -23,6 +23,36 @@ def tearDown(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
u = yield User().save()
View
@@ -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

0 comments on commit c239dd8

Please sign in to comment.