Models

We define models as assets you interact with in a blockchain.

Every data structure should be a model, since it defines what are the minimum necessary properties to be present.

The package  @worldsibu/convector-core-model contains the necessary code to create models. Here's an example of one:

Notice we're extending ConvectorModel. This class is full of rich methods you can use to manipulate the data.

There are multiple decorators you can use to model the data:

  • @ReadOnly() - used when you want a property to be set once and then sealed to modifications
  • @Required() - used when you want the property to be ensured there will be a value
  • @Default(val | () => val) - used when you want to provide a default value before saving the data to the blockchain if there was no value provided
  • @Required(Schema|Model) - used to validate the property to conform a format

Here's a more complex example with nested objects and arrays

Usage

To create a base model file through Convector CLI run.

conv generate model <NAME-OF-MODEL>
	

Then you can edit it and adapt it as you need.

More advanced

The children classes can be used in 1 of 3 ways:

1. As an model query

or

2. As a param constructor and validator

3. As a container to start filling the model

API

Models are based on ConvectorModel<T>, and it provides some basic static methods to use on models.

Querying the chaincode

Some static methods are present for you to query the chaincode storage. All these methods are subject to the  storage capabilities, for example, using storage-couchdb you will be able to query the database in a more fashion way, even using views.

Basic properties

All models are required to have an  id and a type field. The declaration of both can be omitted if wanted, but both of them must have a value. If you pass a string as the only param while instantiating a model, it will be used as the ID of that model.

Base methods

  • To fetch the model content from the ledger and load the data into a model use async myModel.fetch(), the ID must have been set before this
  • To create or update a whole model in the blockchain you must use async myModel.save()
  • To update a portion of an existing model in the blockchain you must use async myModel.update({ changes })
  • To delete the model content in the blockchain you must use async myModel.delete() however, notice that a delete in blockchain terms, is just removing the current value from the state, but the historical data will still be there and cannot be removed
  • To clone a model you can use myModel.clone()
  • To convert a model to json you can do JSON.stringify(myModel) or myModel.toJSON()
  • To get the historical changes of a model you can do myModel.history(). This will return an array of objects containing the txId, the timestamp, and the value through the time.

FlatConvectorModel

The ConvectorModel type is pretty convenient as it enhances your code by accepting decorators for example (which auto-generate validations for you). But a class extending the ConvectorModel type will also have multiple functions you may not want in your properties inside of model, for example .save() .getOne() and so on. That would be confusing for your code base and your team.

Sometimes you need to add a nested property inside of your object where the nested property won't exist by itself (it won't be saved or queried separately from the parent object). But having decorators is quite useful. So to have both? The solution to such scenario is adding the property as a FlatConvectorModel, with this you will keep the ability to add decorators but it won't drag all the functions a regular ConvectorModel brings.

In your code, this would look like this:

With this, validations will be propagated through the child objects.

Lazy loading

Some complex scenarios may need you to have circular dependencies, so how can we handle this scenario with such dynamic validations? There's a new property since 1.3 in which you can use `yup.lazy` to avoid circular dependencies issues.

Inheritance

Inheritance is another hot feature enabled after 1.3. Inheriting object types is required in complex scenarios but one may expect that even validations may be inherited, right? It's possible to achieve this in this way:

Did this answer your question? Thanks for the feedback There was a problem submitting your feedback. Please try again later.

Still need help? Contact Us Contact Us