25.3.1The SandstoneDB API
SandstoneDB has a very simple API for querying and iterating on the classes representing the repository for their instances:
Class Query API. The API looks a lot like the standard Smalltalk collection protocol slightly renamed to make it clear these queries could potentially be more expensive than just a standard collection.
-
atId:andatId:ifAbsent:allow one to access an instance of the receiver based on its ID. Here is an example ofatId:use.
handleAccountEnable: aRequest
| auction |
(aRequest url endsWith: '/enable-account') ifTrue:
[ auction := CAAuction atId: (self fieldsAt: #id).
self session pendingAction: 'User has been enabled!' ->
[ self session user isAdmin ifTrue:
[ auction seller
isDisabled: false;
commit ] ] ]
-
do:iterates over all the instances of the class but does a copy in case the do modifies the collection. -
find:returns the first instance satisfying the predicate, as dofind:ifAbsent:andfind:ifPresent:.findAll:returns all the instances that match a predicate. Here is an example offindAll:.
isValidAuctionVin: aVin
^ (CAAuction findAll: [ :each | each vin = aVin ])
allSatisfy: [ :each | each isClosed ]
-
findAllreturns all the instances of the class.
Instance API. There’s a simple API for the instance side:
-
idreturns a UUID string in base 36 which uniquely identifies the instance. -
createdOnandupdatedOnreturn the timestamps of the creation and last update of the instance. -
versionreturns the version of the instance. The version is increased for each save. It is useful in critical sections to validate you’re working on the version you expect.
-
indexStringreturns all instance variable’asStrings as a single string for easy searching.
Instance Actions. Here is the list of actions you can perform on a record.
-
savesaves the instance but is not thread safe. -
critical:grabs or creates a Monitor for thread safety. -
commitis just asavein acritical:session. -
commit:is similar tocommitbut you can pass a block if you have other work you want done while the object is locked. -
abortChangesrolls back to the last saved version. -
deletedeletes the instance. -
validateis a hook that subclasses can override to specify validation action and throw exceptions to prevent saves.
Here are some trivial examples of using an SDActiveRecord.
person := Person find: [ :each | each name = 'Joe' ].
person commit.
person delete.
user := User
find: [ :each | each email = 'Joe@Schmoe.com' ]
ifAbsent: [ User named: 'Joe' email: 'Joe@Schmoe.com' ].
joe := Person atId: anId.
managers := Employee findAll: [ :each | each hasSubordinates ].The framework offers some hooks that you can override on record life cycle events. But pay attention to invoke the superclass methods.
-
onBeforeFirstSave -
onAfterFirstSave -
onBeforeSave -
onAfterSave -
onBeforeDelete -
onAfterDelete
There is also a testing method you might find useful: isNew answers true prior to the first successful commit.