3. Creating Entities
Introduction to the Entity concept
Entities are the natural place for abstractions from your domain. Usually, big things like User, Order, Contract Agreement, Shopping Cart, Schedule, etc. are entities.
Entities have properties (fields), actions (methods) and often is uniquely identified by an ID.
Refer to Getting Started - What's and Entity to know more.
For this project, the most basic entity is the User. The CLI generates it out-of-the-box, so let's understand how it works:
Generated User Entity
First, let's understand how entity code works:
// Path: src/domain/entities/user.js
/*
First, import from herbsjs package the main functions
to create a entity, define entity fields and make
entity avaible for application.
*/
const { entity, id, field } = require('@herbsjs/herbs')
const { herbarium } = require('@herbsjs/herbarium')
/*
Here we start a const called User, thats receives
from entity() function a instance of Entity that will
represent an User.
The entity() function expects two arguments,
in this sintax entity(entity_name, entity_body).
- First argument entity_name is a string thats determines this Entity name
- Second argument entity_body is a object with properties
thats represents Entity attributes
*/
const User = entity('User', {
// The key of this object defines a field name.
// The value is the object type of determined by `field()` function.
// `id()` is a special field to define a entity unique identifier.
id: id(Number),
// Both the fields "nickname" and "password" are texts, therefore we are using `String`.
nickname: field(String),
password: field(String)
})
/*
Finally we are exporting our entity, but we don't do
this direct like `module.exports = User`.
herbsjs works with automagic dependecy injection, so to do
magic works we will need use a herbarium to export our entities
and make it avaible for all application.
It's only necessary pass to module.export, herbarium.entities.add().entity,
passing by add() as first argument our entity object, in this case is User,
and as second argument a string with a name of entity 'User'.
*/
module.exports =
herbarium.entities
.add(User, 'User')
.entity
Entity fields
In the User entity, we has seen the fields:
- id: The unique identifier for the user.
- nickname: The nickname for the user like "user123".
- password: The user's access password.
But within the entity fields properties, we can do more, is possible set a default value for a field or make some validation, for now, is important know the type of field are Scalar types, tere are some of them:
Number
: double-precision 64-bit binary format IEEE 754 valueString
: a UTF‐16 character sequenceBoolean
: true or falseDate
: represents a single moment in time in a platform-independent format.
List Entity
For our TODO api we need 2 entities, List and Item, first let's creates a list.
for this entity let's reuse a User Entity previous auto generated by herbs-cli
Rename de file from user.js to list.js
src/domain/entities/user.js
->src/domain/entities/list.js
Inside a file let's rename User to List
From this
const User = entity('User', { ...
To this
const List = entity('List', { ...
Rename in exports to
From this:
module.exports =
herbarium.entities
.add(User, 'User')
.entityTo this:
module.exports =
herbarium.entities
.add(List, 'List')
.entityFinaly, let's update fields for List Entity
From this:
{
id: id(Number),
nickname: field(String),
password: field(String)
}To this:
{
id: id(Number),
name: field(String),
description: field(String)
}
Now our List entity code will looks like:
const { entity, id, field } = require('@herbsjs/herbs')
const { herbarium } = require('@herbsjs/herbarium')
const List = entity('List', {
id: id(Number),
name: field(String),
description: field(String)
})
module.exports =
herbarium.entities
.add(List, 'List')
.entity
and as a final touch, delete user folder inside src/domain/usecases/
, because we will run the herbs update
command that will create the uses cases for our new entity, besides of repository and migration files that we will deal with in the next steps.
Item Entity
Let's create a new entity Item
create a file
item.js
inside foldersrc/domain/entities/
very similar with List lets create our Item entity code:
//start a file importing dependencies:
const { entity, id, field } = require('@herbsjs/herbs')
const { herbarium } = require('@herbsjs/herbarium')
/*
create a const Item and assign a entity()
passing all arguments needed with fields for the item
*/
const Item = entity('Item', {
id: id(Number),
name: field(String),
completed: field(Boolean)
})
// finally exports Item entity
module.exports =
herbarium.entities
.add(Item, 'Item')
.entityagain after create a entity let's run the
herbs update
command and keep things up to date.
Entity fields default value
When CLI generate code to us, we have a just a base, but we can go further.
Just for example, imagine that Item entity as a task, so when we created it, the field completed
must be
false, because we don't do task yet.
To make this happen, we can set a default value for field completed
, we just need
adapt our entity creating code to:
// src/domain/entities/item.js
const Item = entity('Item', {
id: id(Number),
name: field(String),
completed: field(Boolean, {
default: false
})
})
Learn more about default values.
Entity fields validation
Once we have the fields set, other important thing to do is implement validation to them. For example, when we create a List, we need indentify there, so we will set a name, but to prevents thats some user try save a list whitout a name we can set a validation to field name, thats make field be required.
The validation is passed as an Object
and it can have different kinds of parameters, such as presence, length and numericality. For example:
In our List entity will set some validations in field id
to make it required, just accept integer values an must be greater than 0 and field name
to be required and have a minimum of three letters.
// src/domain/entities/List.js
...
const List = entity('List', {
id: id(Number, {
validation: {
// The field MUST be present
presence: true,
numericality: {
// Must be greater than 0
greaterThan: 0,
// Cannot be a float
onlyInteger: true
}
}
}),
name: field(String, {
validation: {
// The field MUST be present
presence: true,
// Here, the name MUST have 3 letters at least
length: { minimum: 3 },
}
}),
description: field(String)
})
Learn more about validations with Herbs.
Feel free to implement more fields and add different kinds of validation to it.
Now that we have the List and Item entities, let's move on to setting up a database, where we will save our Lists and Items.