
JsModels facilitates the use of models in your application.
About
JsModels helps you abstract the layer of your app responsible for representing business data and logic.
JsModels facilitates the creation of a model with CRUD methods wired up to a method to make the API Request.
It also let you validate your model before making the API request with some out of the box validations.
const JsModel = const PersonApi = static { return PersonApi } static { return "id" "name" "occupation" } const person = personname = "Walter Reyes"personoccupation = "Icalia Labs Coder" person
Installation
npm install javascript-models
Table of Contents
Creating a JsModel
- Create a Model Class and inherit form JsModel
- Create a Model Api Class and implement the necessary methods.
const PersonApi = static { return PersonApi }
Filling the methods in your API Class
This is the template of all the current methods wired to the API class.
Each method implementation should return a Promise
to work.
If the method is not implemented, or implemented incorrectly JsModel with handle it gracefully telling you what's not working with a rejected promise.
// Wired up to `Person.create(params)` and `person.save()` static {...} // Wired up to `person.update()` static {...} // Wired up to `Person.updateAll(params)` static {...} // Wired up to `person.destroy()` static {...} // Wired up to `Person.find(params)` static {...} // Wired up to `Person.all(params)` static {...} // Wired up to `Person.first(params)` static {...} // Wired up to `Person.findBy(params)` static {...} // Wired up to `Person.where(params)` static {...}
Generator
You can always use the JsModel generator to autogenerate your Model Class and Model Api Class.
First install the generator and the simply run:
jsmodels generate <ModelName>
You should see a new models/
directory and two new files inside it:
- The Model file ->
models/ModelName.js
- The API file ->
models/ModelNameApi.js
You can also customize the paths for your models and api.
The Model Attributes
You need to specify the attributes your model is allowed to have.
Simply override the static method ATTRIBUTES
.
static { return "id" "name" "occupation" }
Now when you call the constructor it will initialize a hash with the attributes you setted up.
const person = console // {id: null, name: null, occupation: null}
Also if you send params to the constructor it will only allow the attributes in ATTRIBUTES
const person = id: 1 name: 'Walter' age: 24console // {id: 1, name: 'Walter', occupation: null}
CRUD: Reading and Writing Data
To use the following methods you need to implement how your API will handle each request.
If your API does'nt implement some methods, you don't need to use them and if you do JsModel will tell you that the method is not properly implemented.
Create
JsModels can be created from a hash with the create
method and it will return the promise returned from the API postCreate
method.
personParams = id: 1 name: 'Walter' occupation: 'Coder' age: 23 Person
Using the new keyword, an object can be instantiated without being saved.
let person = personname = 'Walter'personoccupation = 'Coder'
You could also set the params with the constructor
person = personParamsconsole // Walter
A call to person.save()
will call postCreate
on the PersonApi with the instance params.
person
Read
JsModel provides some wired methods to access your models.
Each method is wired up to a method in the API class. You would need to fill those methods to use them properly.
.find
Model.find
is wired up to the method getFind
in the ModelApi.
Person
.all
Model.all
is wired up to the method getAll
in the ModelApi.
PersonallqueryParams
.first
Model.first
is wired up to the method getFirst
in the ModelApi.
Person
.findBy
Model.findBy
is wired up to the method getAll
in the ModelApi.
Person
.where
Model.where
is wired up to the method getAll
in the ModelApi.
Person
Update
You can retrieve an instance and then call update
to call the method putUpdate
with the instance params.
const person = Person.findBy({name: 'Walter'})person.name = 'David'person.update().then((response) => { console.log(response)}).catch((error) => { console.log(error)})
A shorthand for this is to use a hash mapping attribute names to the desired value, like so:
const person = Personperson
This is most useful when updating several attributes at once, if you would like to update them in bulk you could call updateAll
Person
Delete
Likewise, once retrieved an JsModel can be destroyed calling destroy()
which will call deleteDestroy(instanceParams)
on the api.
const person = Personperson
Validations
JsModel let you validate the state of a model before making the API request.
We include many methods that you can use to check your models and validate that an attribute value is not empty, follow a specific format, has some length and many more.
All writable operations, except of destroy
, call the validations before the API request.
So create
, save
, update
, updateAll
will call the validations before making api request.
You can also check that a model is valid calling isValid()
or isInvalid()
on an instance.
Setting Validations
... static { return "id" "name" "occupation" "email" } static { return name: length: min: 4 max: 16 email: email: {} }
This would check that the name has a length is between the range of 4 and 16 and the email has the correct format.
const person = personname = 'Walter'personemail = 'not-a-valid-email'person
The Response returned from the validations has the following format:
type: 'error' status: 0 ok: false data: error: 'Model is not valid' model: instanceOfModelWithErrors
The
You can check the full list of available validations here
Custom Validators
Custom Validators are classes that allow you to write customized validations for your model.
They need to implement a Dictionary of Validations and a set of validations function that will be used in your Model.
class PersonCustomValidator { static VALIDATIONS_DICTIONARY() { return { legalMexicanAdult: this.legalMexicanAdult, validationWithParams: this.validationWithParams } } static legalMexicanAdult(age, args = {}) { return age > 18; } static validationWithParams(value, args = {}) { console.log(args) return true; }}
and then you simply specify that your model uses this Custom Validator
static { return PersonCustomValidator } static { return "id" "name" "occupation" "email" "age" } static { return age: legalMexicanAdult: {} name: validationWithParams: param: 1 param: 2 }
and that's it. Then you can use legalMexicanAdult
and validationWithParams
in your Person Validations.
RoadMap.
Administrate: An Out of the Box Backoffice for your models.
If an application have all their business data in JsModels we know that they have a set of validations, and some standard name to read them, create them, update them and destroy them.
With these information we could provide an fully function backoffice out of the box for your models.
And even better: backend agnostic. You could implement your API Request with whatever backend you are using: Rails, Firebase, Django, etc.
Handle relationships.
Currently you could add a foreign key as an attribute and fetch the relationships of your model.
But it would be great if JsModel could provide the mechanism to fetch those associations out of the box. Given the proper API implementations.
A Rails Backend Scaffold for your models.
Rails could provide a scaffold for your models that implements all of the available requests JsModels using some standard like JSON API
This way it would be way easier to make an API and connect it with a Client Side App