Validate field data

Accurate and valid data is essential to ensure the success of any application Tailor Platform provides an easy way to validate data, with its main database, Tailor DB. Tailor DB allows users to define validation rules within their data model, enabling them to ensure their data is accurate and valid.

This tutorial demonstrates how to apply Tailor DB data validation rule to your data.

  • Complete Quickstart first If you haven't yet built the Inventory-tracker app from our template.
  • See Core concepts to get an overview of Workspace, Organization, Application and Service.

Tutorial steps

Follow these steps to add a validation rule to the priority field of a Task:

  1. Define validation rule in product.cue file
  2. Apply the change using tailorctl
  3. Confirm the applied validation rule

1. Define validation rule

To define a validation rule, we can add a validate array field to the description data schema. In this tutorial, we will add a rule to deny values that are greater than or equal 40 for the description value.

The following CUE file is an example of validation, which is to deny values either above 5 or below 1. expr is a string of CEL-go expressions. The action to execute for rules must be one of the following: tailordb.#Permit.Allow, tailordb.#Permit.Deny, or tailordb.#Permit.Skip. Other accessible values and functions, please refer to the Tailor DB data validations guide.

<span><span style="color: var(--shiki-color-text)">description: {</span></span>
<span><span style="color: var(--shiki-color-text)">  Type:        tailordb.#TypeString</span></span>
<span><span style="color: var(--shiki-color-text)">  Description: </span><span style="color: var(--shiki-color-text)">&quot;</span><span style="color: var(--shiki-token-string-expression)">Description of the product.</span><span style="color: var(--shiki-color-text)">&quot;</span></span>
<span><span style="color: var(--shiki-color-text)">  Validate: [{</span></span>
<span><span style="color: var(--shiki-color-text)">    Expr: </span><span style="color: var(--shiki-color-text)">&quot;</span><span style="color: var(--shiki-token-string-expression)">!(length(_value) &lt; 40)</span><span style="color: var(--shiki-color-text)">&quot;</span></span>
<span><span style="color: var(--shiki-color-text)">    Action: tailordb.#Permit.Deny</span></span>
<span><span style="color: var(--shiki-color-text)">    ErrorMessage: </span><span style="color: var(--shiki-color-text)">&quot;</span><span style="color: var(--shiki-token-string-expression)">Description length should be less than 40 characters.</span><span style="color: var(--shiki-color-text)">&quot;</span></span>
<span><span style="color: var(--shiki-color-text)">  }]</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>

2. Apply the change using tailorctl

Generate new workspace CUE file and apply the Tailor DB changes.

<span><span style="color: var(--shiki-token-function)">cue</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">eval</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">-f</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">manifest/workspace.cue</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">-o</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">generated/workspace.cue</span></span>
<span><span style="color: var(--shiki-token-function)">tailorctl</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">workspace</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">apply</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">-m</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">generated/workspace.cue</span></span>
<span></span>

3. Confirm the applied validation rule

<span><span style="color: var(--shiki-token-comment)"># Open the GraphQL playground in the browser</span></span>
<span><span style="color: var(--shiki-token-function)">tailorctl</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">workspace</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">app</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">open</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">-n</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">inventory-tracker</span></span>
<span></span>

Let's create a Product resource with a description that is above the allowed length. By running the following mutation, we will receive a message stating description: validation failed, indicating that the action has been denied due to the validation rule.

<span><span style="color: var(--shiki-token-keyword)">mutation</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)">  createProduct(input: { </span><span style="color: var(--shiki-token-string)">description</span><span style="color: var(--shiki-color-text)">: </span><span style="color: var(--shiki-token-string-expression)">&quot;Comfortable, antibacterial socks made from bamboo fibers&quot;</span><span style="color: var(--shiki-color-text)"> }) {</span></span>
<span><span style="color: var(--shiki-color-text)">    id</span></span>
<span><span style="color: var(--shiki-color-text)">  }</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
<span><span style="color: var(--shiki-color-text)">{</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-keyword)">&quot;errors&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> [</span></span>
<span><span style="color: var(--shiki-color-text)">    {</span></span>
<span><span style="color: var(--shiki-color-text)">      </span><span style="color: var(--shiki-token-keyword)">&quot;message&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;description: Description length should be less than 40 characters.&quot;</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">      </span><span style="color: var(--shiki-token-keyword)">&quot;locations&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> [</span></span>
<span><span style="color: var(--shiki-color-text)">        {</span></span>
<span><span style="color: var(--shiki-color-text)">          </span><span style="color: var(--shiki-token-keyword)">&quot;line&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">1</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">          </span><span style="color: var(--shiki-token-keyword)">&quot;column&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">34</span></span>
<span><span style="color: var(--shiki-color-text)">        }</span></span>
<span><span style="color: var(--shiki-color-text)">      ]</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">      </span><span style="color: var(--shiki-token-keyword)">&quot;path&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> [</span></span>
<span><span style="color: var(--shiki-color-text)">        </span><span style="color: var(--shiki-token-string-expression)">&quot;createProduct&quot;</span></span>
<span><span style="color: var(--shiki-color-text)">      ]</span></span>
<span><span style="color: var(--shiki-color-text)">    }</span></span>
<span><span style="color: var(--shiki-color-text)">  ]</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-keyword)">&quot;data&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)">    </span><span style="color: var(--shiki-token-keyword)">&quot;createProduct&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">null</span></span>
<span><span style="color: var(--shiki-color-text)">  }</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>

Next, we will create a Task resource with a priority number that is within the allowed range. By running the following mutation, we can successfully create the resource, as the priority number is within the allowed range of validation rules.

<span><span style="color: var(--shiki-token-keyword)">mutation</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)">  createProduct(input: { </span><span style="color: var(--shiki-token-string)">description</span><span style="color: var(--shiki-color-text)">: </span><span style="color: var(--shiki-token-string-expression)">&quot;Handcrafted scarf&quot;</span><span style="color: var(--shiki-color-text)"> }) {</span></span>
<span><span style="color: var(--shiki-color-text)">    id</span></span>
<span><span style="color: var(--shiki-color-text)">  }</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
<span><span style="color: var(--shiki-color-text)">{</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-keyword)">&quot;data&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)">    </span><span style="color: var(--shiki-token-keyword)">&quot;createProduct&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)">      </span><span style="color: var(--shiki-token-keyword)">&quot;id&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;e10f0541-3521-469c-a269-951b6ba06cc3&quot;</span></span>
<span><span style="color: var(--shiki-color-text)">    }</span></span>
<span><span style="color: var(--shiki-color-text)">  }</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>