Docs‎ > ‎API Creator‎ > ‎Specify your Business Rules‎ > ‎

Logic Event Rule Type

Events are server-side JavaScript-code business logic, providing access to external/reusable functions by way of an open-source implementation of JavaScript called Rhino. They are a key architectural element, providing:

  • Re-use. Table events are re-used over all resources built on that table. When Live API Creator receives resource updates, they are de-aliased onto the underlying Base Table objects.
For more information about resource/object mapping, including de-aliasing column names, see Logic Execution.
  • Encapsulation. Live API Creator automatically invokes event logic as updated requests are processed.
For more information about encapsulations, see Logic Execution.

Rules vs. Events

Use the following as a guideline of when to use rules vs. events:
  • Rules. Reduce the amount of code you need to write. Using rules requires that you transition to "think spreadsheet". Use rules before you build your events.

For more information, see the following "Think Spreadsheet" Rules Example.

  • Events. Events are a complement to the other declarative forms of rules. They address issues not addressed by rules and have unlimited flexibility.

Specify Event Firing

You can specify when the event is fired. Events interact with other logic and fire at predetermined times during logic execution, depending on the event type:

  • Normal. Fire after row-logic is completed. The row data reflects all derivation results. You can alter the row, but you must use logicContext.save() to ensure that required logic is executed.
  • Early. Fire before your logic executes. The row data has not been subjected to formulas and other derivations. You can change the row, and the changes are subjected to validations, other chained logic, and saved.
  • Commit. Fire after all row-logic is complete, for all the rows in the transaction. The rows reflect all the logic processing. You cannot change the rows at this point.

For more information:

"Think Spreadsheet" Rules Example

The following is a common example. Assume you need a sum (or count) of child rows for a parent, for example, a sum of unpaid order amounts. Events are a familiar concept, so experienced programmers may envision the following code, perhaps as part of the Use Case "Add Order", to adjust sums and counts:

Define Order event MaintainCount as
if (logicContext.initialVerb == 'INSERT' && row.isPaid == false) { // row is the order
customer = row.customer; // parent accessor
customer.balance += row.amountTotal;
logicContext.update(customer);
}

Consider the other use cases:
Delete Order: Decrement the count - if the order isPaid.
Change Order.isPaid: Watch for such a change, and if you detect it, adjust the sum by amountTotal.
Change Order.amountTotal: Watch for such a change, and if you detect it, adjust the sum by the difference.
Reassign Order: Often overlooked, reduce the old customers' balance, increment the new one, only if the order isPaid.
If the qualification condition or summed field (amountTotal) is itself derived, perhaps from still another table, the code can get complicated. Define a sum or count and all of the boilerplate code to address the use cases above are handled without error. Sums and counts operate just like spreadsheets:

  Spreadsheet Reactive Logic
 User Define cell formula

Cell A =
    Sum(ColumnB)
 Define Database column

Customer.balance =
      sum(orders.amountTotal where paid = false)
 System Watch for changes
  • ColumnB changes
  • ColumnB new rows
  • ColumnB deleted rows
 Watch for changes
  • amountTotal changes
  • paid changes
  • Foreign Key changes (Orders.CustomerName)
  • Inserted Orders
  • Deleted Orders
  Reacts to changes
  • Adjust CellA
 Reacts to changes
  • Adjust Customer.balance (SQL and transaction management)

Use Events

Supply JavaScript table event handlers. Like all JavaScript rules, an event has access to the standard variables including row, oldRow, and logicContextThe logic engine invokes these on every update, providing key contextual information including:
  • row - This object has attributes for every column, so you can refer to a order's row.amount_total. It also provides role accessors, so you can refer to an orders' row.customer.balance, or obtain a collection of row.lineitems (a collection of lineitem rows). Rows also provide persistence to read/alter data.
  • oldRow - Attributes for the pre-updated version of the row, so you can detect changes.LogicContext - Provides many services, such verb (insert, update or delete), services to read and write data (including logic enforcement), create new objects, event logging, etc.
  • logic.sys - System methods, including InsertIntoFrom (auditing and deep copy), Allocation, and findWhere (collection filtering).

For more information:

Logic Event Examples

A typical example is an auditing event. The use of the current/old bean in making your logic conditional:

if (row.amount_total != oldRow.amount_total) 
    SysLogic.insertChildFrom("purchaseorder_audit", logicContext);

Event Context

Live API Creator passes contextual variables to your events, such as row, oldRow, and logicContext. Live API Creator pre-supplies methods, identified with SysLogic. For more information, see System MethodsYou can also invoke JavaScript methods, including systems supplied ones. For a list of the methods, see reference.

Database validation depends on your validation logic, so the system must ensure this is executed after any changes you make. This applies to events. For more information about updating an object, see Update an objectLive API Creator can execute update logic multiple times, but associated events fire only once per transaction.