Runnable Api Client
varuser=newRunnable();varuser=newRunnable();user.githubLogin(function(err,body){// ...});varuser=newRunnable();user.githubLogin(token,function(err,body){// ...});varuser=newRunnable();user.logout('user','pass',function(err,body){// ...});varuser=newRunnable();user.login('user','pass',function(err,body){// fetch a specific resourcevarproject=user.fetchProject(projectId,function(err,body,code){// project becomes a project model});// factory methods and parent actionsproject=user.newProject(attrs,opts);project=user.fetchProject(projectId,cb);project=user.createProject({json: data},cb);project=user.updateProject(projectId,{json: data},cb);user.destroyProject(projectId,cb);// model methodsproject.fetch(cb);// fetch latestproject.update({json: attrs},cb);// update the resource attrsproject.destroy(cb);// delete the resource through the apiproject.toJSON();// last clientside known state of the resource// fetch a collection of resourcesvarprojects=user.fetchProjects(projectId,function(err,body,code){// project becomes a collection of projects});projects.models;// are all models of the resources fetched});Runnable api client's directory structure follows the api url structure and the structure of our resources.
Project environments are a nested resource - /projects/:id/environments/:id
Note: the singular form of each resource used for the folder and file names.
'use strict';varutil=require('util');varBase=require('../base');varurlJoin=require('../../url-join');module.exports=Environment;functionEnvironment(attr,opts){opts=opts||{};opts.urlPath=urlJoin(opts.parentPath,'environments');returnBase.apply(this,arguments);}util.inherits(Environment,Base);All (99%) of the new models will inherit from the Base Model class like the example above.
Nested Models use urlJoin(opts.parentPath, <relativePath>) create their urlPath using
opts.parentPath. opts are being passed to the constructor from extend-with-factories
which is explained below. First level resources like Projects (/projects), just need their
urlPath set directly Projects.prototype.urlPath = 'projects' or opts.urlPath = 'projects'.
The parent model in this example is Project. Here is the Project Class:
varutil=require('util');varBase=require('./base');module.exports=Project;functionProject(){returnBase.apply(this,arguments);}util.inherits(Project,Base);Project.prototype.urlPath='projects';Add the following line to the parent model to automagically create submodel factory/action methods:
require('../extend-with-factories')(Project);varprojectId="real-project-id";varuser=newRunnable(),environment;user.anonymous(function(err){if(err){throwerr;}varproject=user.fetchProject(projectId,function(err){if(err){throwerr;}// automagical environment factory methods:environment=project.newEnvironment(attrs,opts);// create a new environment instanceenvironment=project.fetchEnvironment(projectId,cb);// fetches an environment instance from the api serverenvironment=project.createEnvironment({json: attrs},cb);// makes a post request to create a new environment// automagical environment action methods:project.updateEnvironment(projectId,{json: attrs},cb);project.destroyEnvironment(projectId,cb);// Action methods inherited by the Base Modelenvironment.fetch(cb);// get latest data from serverenvironment.update({json: attrs},cb);environment.destroy(cb);});});Creating a collection is very similar to the model example. The only difference is that you
should inherit from the Base collection. Also, factory methods created use the plural form
of the resource name - Ex: project.getEnvironments(cb). There are examples of all types of
models and collections (first level and nested), when in doubt look for an existing example
in the code base.