A model/collection library
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
fixtures
spec
src
.gitignore
LICENSE
README.md
main.js
package.json

README.md

Model

This library contains the foundamental classes that allow modelling and managing the data layer of a front/back-end JavaScript application.

Intro

Once JSON data becomes available, we often have the need to encapsulate them in more structured and clever business objects that will help us making decisions on what to do with our raw data.

The two main type of entities needed are normally models and collections. Both are implemented in the library.

Model

A model can be instantiated like so:

var person = new Model({
   name: "Nourdine",
   age: 33
});

Once instantiated its properties can be easily get, set, removed or checked to make sure they exist at all. Here's some code:

person.get("name"); // Nourdine
person.has("name"); // true
person.get("age"); // 33
person.set("age", 42);
person.get("age"); // 42
person.remove("age");
person.get("age"); // undefined
person.has("age"); // false

Easy no? Now we can extend the Model class to add interesting methods that can simplify our software and address some of the properties more explicitly.

class Person extends Model {

   getName() {
      return this.get("name");
   }

   getAge() {
      return this.get("age");
   }

   isOldEnough() {
      return this.getAge() >= 18;
   }

   prettyPrint() {
      return this.getName() + " : " + this.getAge(); 
   }
}

Finally, models can be turned into the original object literal that was passed in when the model was initially created.

var person = new Person({
   name: "Nourdine",
   age: 33
});

person.toLiteral(); // { name: "Nourdine", age: 33 }

Composing models

Let's now assume we have the following piece of json:

{
   name: "fabs",
   age: 33,
   address: {
      street: "Long Street",
      town: "Cape Town",
      country: "South Africa"
   }
};

It is pretty clear that here are represented tw odifferent entities: a person and his/her address.

A good way to go about this is using composition of objects. Here's how:

// First of all let's create a model to adequately represent the "address" idea...

class Address extends Model {

   getStreet() {
      return this.get("street");
   }

   getTown() {
      return this.get("town");
   }

   getCountry() {
      return this.get("country");
   }
}

// ...now let's subclass `Person` in order to have a model containing and internal `Address` submodel.

class LocalizedPerson extends Person {

   constructor(attributes) {
      super(attributes);
      this.set("address", new Address(this.get("address")));
   }

   isSouthAfrican() {
      return this.get("address").getCountry() === "South Africa";
   }
}

We can now have more sensible code such as:

var lp = new LocalizedPerson({
   name: "fabs",
   age: 33,
   address: {
      street: "Long Street",
      town: "Cape Town",
      country: "South Africa"
   }
});

if (lp.isSouthAfrican()) {
   console.log("Howzit!?");
   console.log("Shaaaaaame");
   console.log("Lekker!");
}

Model events

Every Model instance is also an instance of PubSub (see the PubSub library documentation).

When using a Model the following events will be triggered:

  • set: a callback with the following signature can be registered: (event, propertyName, oldValue, newValue)
  • removed: a callback with the following signature can be registered: (event, propertyName, value)

Here's a snippet showing of how events work:

var person = new Person({
   name: "Nourdine",
   age: 33
});

person.subscribe("set", (ev, propertyName, oldValue, newValue) => {
   console.log(`The property '${propertyName}' has changed from '${oldValue}' to '${newValue}'`);
});

person.subscribe("removed", (ev, propertyName, value) => {
   console.log(`The property '${propertyName}' holding the value '${value}' has been deleted`);
});

person.set("name", "Laurent");
// it will log: The property 'name' has changed from 'Nourdine' to 'Laurent'

person.remove("name");
// it will log: The property 'name' holding the value 'Nourdine' has been removed

Collections

[coming soon]

Collections events

[coming soon]