@ninetynine/node-models v1.0.1
Contents
Installation
node-models can be installed with NPM or Yarn.
# Installing with NPM
npm i --save @ninetynine/node-models# Installing with Yarn
yarn add @ninetynine/node-modelsInitial Setup
Currently the only supported driver is lowdb, check it out here. There are plans for supporting more drivers- feel free to open a PR to implement other drivers.
By default lowdb's store file will be placed in the project root under the directory storage:
# Default path for store file
<root>/storage/db/lowdb.jsonYou can change the default path (not filename) by setting process.env.STORAGE_PATH, this can be accomplished easily by using dotenv.
Usage
Creating
To create a model simply extend the Model class from @ninetynine/node-models:
// An example of a minimal model
// ./models/user.js
const Model = require('@ninetynine/node-models')
class User extends Model {
//
}
module.exports = UserDefining The Table
By default the table name is assumed by making use of pluralize:
User -> users
UserLog -> user_logsTo define your own table return a string from the table get:
// An example of defining the table name
// ./models/user.js
const Model = require('@ninetynine/node-models')
class User extends Model {
get table() {
return 'unexpected_table_name'
}
}
module.exports = UserThe table name is used when storing and finding instance of the model.
Defining The Primary Key
By default the primary key is assumed id. To define your own primary key return a string from the primaryKey get:
// An example of defining the primary key
// ./models/user.js
const Model = require('@ninetynine/node-models')
class User extends Model {
// <snip>
get primaryKey () {
return 'unexpected_primary_key'
}
}
module.exports = UserThis key is used when storing and finding instances of the model.
Defining The Foreign Key
By default the foreign key is assumed as the snake case name of the model suffixed by _id:
User -> user_id
UserLog -> user_log_idTo define your own foreign key return a string from the foreignKey get:
// An example of defining the foreign key
// ./models/user.js
const Model = require('@ninetynine/node-models')
class User extends Model {
// <snip>
get foreignKey () {
return 'unexpected_foreign_key'
}
}
module.exports = UserThis key is used when referencing the model from a relation.
Defining Model Relationships
To define relations return an object from the relations get:
// An example of defining relations
// ./models/user.js
const Model, { util } = require('@ninetynine/node-models')
const Address = require('./address')
const Role = require('./role')
class User extends Model {
// <snip>
get relations () {
return {
address: {
type: util.relation.belongsTo,
model: Address
}
role: {
type: util.relation.hasOne,
model: Role,
key: 'role_id'
}
}
}
get fillables() {
return [
'address_id'
]
}
}
module.exports = UserReltions work as you might expect:
belongsTowill check the ID on the current model (address_id) against the model (Address) and return one instancehasOnewill check the current ID (id) as a foreign key (user_id) of the instance against the model (Address) and return one instancehasManywill check the current ID (id) as a foreign key (user_id) of the instance against the model (Address) and return multiple instances
If no relation is found then undefined is returned.
A relation will be returned if an attribute with the same name doesn't exist.
Defining Fillable Attributes
To define fillable attributes return an array of strings from the fillables get:
// An example of defining fillable attributes
// ./models/user.js
const Model = require('@ninetynine/node-models')
class User extends Model {
// <snip>
get fillables () {
return [
'first_name',
'last_name',
'email_address',
'password'
]
}
}
module.exports = UserFillable attributes allow you to set an attribute safely.
Defining Hidden Attributes
To define hidden attributes return an array of strings from the hidden get:
// An example of defining hidden attributes
// ./models/user.js
const Model = require('@ninetynine/node-models')
class User extends Model {
// <snip>
get hidden () {
return [
'password'
]
}
}
module.exports = UserHidden attributes hide specific attributes when return a model instance as an object.
Defining Attribute Setters
To define attribute setters return an object of functions from the setters get:
// An example of defining attribute setters
// ./models/user.js
const Model = require('@ninetynine/node-models')
class User extends Model {
// <snip>
get setters () {
return {
password: value => (
require('password-hash').generate(value)
)
}
}
}
module.exports = UserAttribute setters are called before an attribute gets set.
Defining Attribute Getters
To define attribute setters return an object of functions from the setters get:
// An example of defining attribute getters
// ./models/user.js
const Model = require('@ninetynine/node-models')
function toTitleCase(str) {
return str.replace(/\w\S*/g, function(txt){
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
});
}
class User extends Model {
// <snip>
get getters () {
return {
first_name: value => (
toTitleCase(value)
),
last_name: value => (
toTitleCase(value)
)
}
}
}
module.exports = UserAttribute setters are called before an attribute gets returned.
Getting And Setting Attributes
Set
There are a few different ways of setting an attribute.
const user = new User
// An example of safetly setting an attribute
user.set('first_name', 'john')
// An example of safely setting multiple attributes
user.fill({
first_name: 'john',
last_name: 'doe'
})
// An example of unsafely setting an attribute
user.setRaw('first_name', 'john')When safely setting an attribute we check to see that the attribute is in fillables and then check for a setter. Using setRaw skips both these steps.
Get
There are a few different ways of getting an attribute.
const user = new User
// An example of safely getting an attribute
user.get('first_name')
// > John
// An example of unsafely getting an attribute
user.getRaw('first_name')
// > johnWhen safely getting an attribute we check to see if that attribute is set, then if there is a getter for that attribute. If no attribute is set then we check the relations, after that we return undefined. getRaw simply returns a key from the internal data object.
Querying
Find
To find an instance of a model simply call find, or pass an ID as the first parameter into the constructor:
// An example of finding an instance of a model
const user
user = new User
user.find(1)
// > Finds user 1
user = new User(2)
// > Finds user 2Find Or Create
To find or create an instance of a model simply call findOrCreate, or pass an ID and object into the constructor:
// An example of finding or creating an instance of a model
const user
user = new User
user.findOrCreate(3, { first_name: 'anne' })
// > Creates user 3 and returns instance
user = new User(2, { first_name: 'john' })
// > Finds user 2findOrCreate saves the data to the store instantly if not found.
Where
To find multiple, or find a single instance, based on more than just an ID simply call where:
// An example of using where to find an instance of a model
const user = new User
user.where({ first_name: 'john' })
// > [ {}, {} ]
user.where({ first_name: 'anne' }, 1)
// > {}If a limited is passed as the second parameter then results will be returned up until that number. If limit is 1 then a single instance is returned, not inside an array.
Update
To update model attributes simply call update:
// An example of updating attributes
const user = new User(1)
// > { first_name: john }
user.update('first_name', 'anne')
user.update({ first_name: 'anne' })
// > { first_name: anne }Compared to calling set or fill update saves to the database after setting the attributes.
Save
To push attributes to the store simply call save:
const user = new User
user.fill({
first_name: 'john',
last_name: 'doe'
})
// > { first_name, last_name }
user.save()
// > { id, first_name, last_name }If the model already has an ID then the model is updated rather than created. If autoIncrement is false then a uuid is generated, otherwise it will add one to the previous entry's ID.
Utilities
Model
To retrieve the current model simply get model:
// An example of getting the current model
const user = new User
user.model
// > UserAuto Increment
By default auto increment is assumed true. To disable it pass false into the getIncrement get:
// An example of setting auto increment
// ./models/user.js
const Model = require('@ninetynine/node-models')
class User extends Model {
// <snip>
get autoIncrement () {
return false
}
// <snip>
}
module.exports = UserThis is used when creating a new model.
Identifier
To get the current identifier simply get id:
// An example of getting an instance ID
const user = new User(1)
user.id
// > 1Next Identifier
To get the next identifier simply get nextId:
// An example of getting the next instance ID
const user = new User(1)
user.nextId
// > 2This is really only useful if you have autoIncrement set to true, otherwise a uuid will be generated each time the property is called.
Exists
To check if an instance exists in the data store simply get exists:
// An example of checking if an instance exists
const user
user = new User
user.exists
// > false
user = new User(1)
user.exists
// > trueDirty
To check if an instance has unsaved changes simply get dirty:
// An example of checking if an instance is dirty
const user
user = new User(1)
user.set('first_name', 'john')
user.dirty
// > true
user.isDirty()
// > trueIs Dirty
To check if an attribute is fillable simply call isDirty:
// An example of checking if an attribute is dirty
const user = new User
user.set('password', 'coolpassword')
user.isDirty('password')
// > true
user.isDirty('first_name')
// > falseSet Dirty
To directly set an attribute to be dirty simply call setDirty:
// An example of setting dirty attributes directly
const user = new User(1)
user.dirty
// > false
user.setDirty('first_name')
user.dirty
// > trueClear Dirty
To directly clean an attribute from being dirty simply call clearDirty:
// An example of clearing dirty attributes directly
const user = new User(1)
user.setDirty('first_name')
user.clearDirty('first_name')
user.dirty
// > false
user.setDirty('first_name')
user.setDirty('last_name')
user.clearDirty()
user.dirty
// > falseIf no attribute is passed into clearDirty then all attributes are marked as clean.
Has Attribute
To check if an attribute is set in the internal data simply call hasAttribute:
// An example of checking if an attribute exists directly
const user = new User
user.hasAttribute('first_name')
// > false
user.set('first_name', 'john')
user.hasAttribute('first_name')
// > trueHas Relation
To check if a relation has been defined simply call hasRelation:
// An example of checking if a relation has been defined
const user = new User
user.hasRelation('address')
// > trueHas Getter
To check if a getter has been defined simply call hasGetter:
// An example of checking if a getter has been defined
const user = new User
user.hasGetter('first_name')
// > true
user.hasGetter('email_address')
// > falseHas Setter
To check if a setter has been defined simply call hasSetter:
// An example of checking if a setter has been defined
const user = new User
user.hasSetter('password')
// > true
user.hasSetter('first_name')
// > falseStore
Has Store
To check if the store has been defined for a specific model simply call hasStore:
// An example of checking if the store has been defined for a specific model
const user = new User
user.hasStore()
// > trueCreate Store
To create the store for a specific model simply call createStore:
// An example of creating the store for a specific model
const user = new User
user.createStore()This also will reset the store if it already exists
Is Fillable
To check if an attribute is fillable simply call isFillable:
// An example of checking if an attribute is fillable
const user = new User
user.isFillable('first_name')
// > true
user.isFillable('id')
// > falseIs Hidden
To check if an attribute is hidden simply call isHidden:
// An example of checking if an attribute is hidden
const user = new User
user.isHidden('password')
// > true
user.isHidden('first_name')
// > falseTo Object
To return an instance of a model as an object simply call toObject:
// > An example of returning a model as an object
const user = new User(1)
// > { id, first_name, last_name, email_address, password }
user.object
user.toObject()
// > { id, first_name, last_name, email_address }To hide attributes from the object define them in hidden. Attributes are ran through getters before being displayed.
FAQ
- Will there be more database drivers in the future?
Yes, there are plans to include
mysqlandsqlitein the future