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 ]
-
findAll
returns all the instances of the class.
Instance API. There’s a simple API for the instance side:
-
id
returns a UUID string in base 36 which uniquely identifies the instance. -
createdOn
andupdatedOn
return the timestamps of the creation and last update of the instance. -
version
returns 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.
-
indexString
returns all instance variable’asString
s as a single string for easy searching.
Instance Actions. Here is the list of actions you can perform on a record.
-
save
saves the instance but is not thread safe. -
critical:
grabs or creates a Monitor for thread safety. -
commit
is just asave
in acritical:
session. -
commit:
is similar tocommit
but you can pass a block if you have other work you want done while the object is locked. -
abortChanges
rolls back to the last saved version. -
delete
deletes the instance. -
validate
is 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.