Model Scripting

Learn about scripting with data models.



let newList = new List().title('x');


let listId = '...';
let list = List.get(listId);
// Because of error handling, 'list' is always defined at this point
let listTitle = list.title;


let listId = '...';
List.get(listId).title = 'new title'; // field/property setter
new List().title('new title').otherField('value'); // fluent setter


let listId = '...';


Since containers create a "scope" for working with other data, a container must be selected before any other operations on its contained data.

To execute code in the context of selected container, pass a function to the container's variable. The return value of the function will be passed back as the return value of selecting the container. Example:

// Load the container 'List'
let listId = '...';
let myList = List.get(listId);

// Select myList, and get all Note titles for myList:
let titleStream = myList(()=>{
   return Note.all().map((n)=>n.title));

// Assuming GET.js, this will result in JSON of Note titles:

Or, the most compact form of same above statements:

let listId = '...';

Keep in mind that when working with containers in dynamic REST paths, the container selection has already occurred.

Common Error Handling

In several examples above, note that null or undefined is not used to represent the absence of a result -- for example List.get and Article.slug never return a null/undefined value.

Instead, an exception is thrown if there is no result. This exception can be left "uncaught" and therefore propagated up to a view setup for routing errors. Or it can be specifically caught using a special nomenclature:

let thingId = '....';
let thing = null;
try {
    thing = Thing.get(thingId);
} catch ($NotFound){
    // At this point we've specifically caught $NotFound,
    // as opposed to catching some unrelated error/exception.
    thing = new Thing();
// At this point 'thing' is always defined.
thing.updateField = 'x';