@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-models
Initial 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.json
You 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 = User
Defining The Table
By default the table name is assumed by making use of pluralize:
User -> users
UserLog -> user_logs
To 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 = User
The 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 = User
This 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_id
To 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 = User
This 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 = User
Reltions work as you might expect:
belongsTo
will check the ID on the current model (address_id
) against the model (Address
) and return one instancehasOne
will check the current ID (id
) as a foreign key (user_id
) of the instance against the model (Address
) and return one instancehasMany
will 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 return
ed 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 = User
Fillable 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 = User
Hidden 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 = User
Attribute 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 = User
Attribute 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')
// > john
When 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 2
Find 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 2
findOrCreate
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
// > User
Auto 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 = User
This 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
// > 1
Next Identifier
To get the next identifier simply get nextId
:
// An example of getting the next instance ID
const user = new User(1)
user.nextId
// > 2
This 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
// > true
Dirty
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()
// > true
Is 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')
// > false
Set 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
// > true
Clear 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
// > false
If 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')
// > true
Has 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')
// > true
Has 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')
// > false
Has 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')
// > false
Store
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()
// > true
Create 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')
// > false
Is 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')
// > false
To 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 getter
s before being displayed.
FAQ
- Will there be more database drivers in the future?
Yes, there are plans to include
mysql
andsqlite
in the future