-
Notifications
You must be signed in to change notification settings - Fork 5
Active Row
activerow
is a hybrid implementation of the Active Record design pattern. Unlike ds_row
which typically represents an existing row, activerow
may not yet exist as a row in the data source. It is designed to be the parent type for your own types and expands on the functionality of ds_row
.
Rows returned from ds
can be cast as activerow
types (or other types based on it) like so:
with row #ds->rows(::activerow) do {
#row->isa(::activerow) // true
}
Or:
with row in #ds->rows(::product) do { // product inherits from activerow
#row->isa(::activerow) // true
}
This allows you to work with your own type definitions in an OOP fashion with minimal overhead and is one of the key strengths of the Datasource suite of tools.
The activerow
type can be created with the following creators:
####-> oncreate(row::ds_row) ####-> oncreate(keyvalue,::database.table) ####-> oncreate(keyvalue,ds::ds)
Alternatively, the subtype should provide either the database name or ds
definition via .database
and .ds respectively. When using either approach you can also specify the table with .table
define product => type {
parent activerow
public ds => ds(::store.product)
}
Or:
define product => type {
parent activerow
data
public database = 'store',
public table = 'products'
}
When .table is blank activerow will use the types name suffixed with "s" as the table.
##Accessing row data — activerow
Data can be accessed in the same fashion as ds_row
with the added benefit of being able leverage your own methods defined in your types. This allows you to format the data in a particular way or create another accessor for the data.
Return the value of the specified column:
#row(column::tag)
-> find(column::tag)
-> find(column::string)
#activerow(::mycolumn)
#activerow->find('mycolumn')
When used in your own types you can create one to one methods like so:
public mycolumn => .find(::mycolumn)
Or you can use methods with different names like so:
public firstname => .find(::user_firstname)
public lastname => .find('user_lastname') // also valid
Bringing it all together:
public qty => .find(::item_qty)
public price => .find(::item_price)
public subtotal => .price * .qty
##Modifying row data — activerow
####-> updatedata(data::trait_foreachpair), updatedata(p::pair,...) Update internal data only — does not write to data source.
#activerow->updatedata(map('price' = 9.95, 'qty' = 3))
####-> update(data::trait_foreachpair), update(p::pair,...) Updates internal data and writes to data source.
#activerow->update(::price = 9.95, ::qty = 3)
// Or
#activerow->update(
map(
'price' = 9.95,
'qty' = 3
)
)
####-> (column::tag) = value, ->(column::string) = value Updates internal data and writes specified value to the data source.
#activerow(::mycol) = 'Value'
#activerow('mycol') = 'Value'
####-> set(column = value), set(column::tag) = value, set(column::string) = value Updates internal data and writes specified value to the data source.
// These all have the same effect
#activerow->set(::mycol) = 'Value'
#activerow->set(::mycol = 'Value')
#activerow->set('mycol') = 'Value'
#activerow->set('mycol' = 'Value')
####-> create Creates new row in the data source and assigns the newly created row to the type.
####-> save Either updates or creates a row depending if it's new or not (based on keyvalue).
####-> delete Clears row data and deletes the row from the data source.
####-> revert Reverts unsaved changes.
Other activerow methods
####-> isnew Returns true if new.
####-> asnew Returns copy of type with a null key value (considered new).
##Changing activerow behavior
You can change the default behaviour of the above by redefining them in your type. For example you may want to perform additional tasks on save or disable deleting by replacing it with an update.
define example => type {
parent activerow
// Extend default save method
public save => {
// Do something else
log(.type + ' saved by ' + current_user->name)
// Now actually save
..save
}
// Override default delete method
public delete => .update(::status = -1)
}