Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Your Basic CRUD: A Simple Tarantool Web App Part 2 (Tarantool 101, Guide 4B)

DZone's Guide to

Your Basic CRUD: A Simple Tarantool Web App Part 2 (Tarantool 101, Guide 4B)

In this second half of the Tarantool CRUD application tutorial, we will add some functionality for “updating” and “deleting” data.

· Web Dev Zone ·
Free Resource

Bugsnag monitors application stability, so you can make data-driven decisions on whether you should be building new features, or fixing bugs. Learn more.

Image title

In our first Tarantool CRUD article (101, Guide 4A), we demonstrated how to build the “create” and “read” functions of a simple web app using only Tarantool and the front-end trio of HTML/CSS/JS. This article continues the app by adding “update” and “delete” to the functionality mix.

As you will see, “update” and “delete” only require a handful of additional lines in our Tarantool code, Tarantool is nice and concise. The entire backend code for the app can actually fit on a single screen with the font at a reasonable size. And you could, of course, reuse this code in the backend of any web app you'd like.

So, let’s start with the Tarantool code, after which we’ll work on the HTML and JavaScript. Note that the repo for the completed app lives here and you can also try a demo.

The Tarantool Backend

For our additional Tarantool code, the file we need to edit is the crud.lua file that resides in /usr/share/tarantool. We’re going to add two functions, “deleted” and “updated.”

Let’s start by adding their routes to our “start” function:

server:route({ path = '/deleted/:id'}, deleted)
server:route({ path = '/updated'}, updated)

We are using two different approaches here. “Deleted” works with a parameter coming in from a route, whereas “updated” works with a posted body.

Now, we’ll write “deleted,” which “stashes” the parameter for the todo ID coming in from the front-end route, converts it to a number, then deletes the corresponding tuple:

function deleted(self)
  local id = self:stash('id')
  local idx = tonumber(id)
  box.space.crudspace:delete(idx)
end

Next, we’ll write “updated,” which ingests two parameters from the body of a front-end post sent by a form (the two parameters are the only ones in our database: the id of a todo as well as its contents). The function converts the id to a number and then accesses the appropriate tuple and updates it with the new todo string. For more details on the options available when “updating” in Tarantool, have a look here.

function updated(req)
  local selfVaredit = req:post_param(data)
  k = tonumber(selfVaredit.todovalue)
  v = selfVaredit.todoname_edit
  box.space.crudspace:update(k, {{'=', 2, v}})
end

That’s it for the Tarantool code.

The HTML Front-End

Most of our new front-end code for updating and deleting will reside in JavaScript, so in our HTML, all we need to add is a form for updating:

<div id="todoform_edit">
  <form id="editatodo">
    <label for="todoname_edit">update a todo</label>
    <input id="todoname_edit" type="text" name="todoname_edit">
    <input type="submit" id="submit" value="submit">
  </form>
</div>

The JavaScript Front-End

Our JavaScript needs the requisite two new functions but also a new map and some changes to the root-route “read” loop that builds the DOM from Tarantool on page reloads.

So, we’ll start by adding a map that will contain our todos and will allow us to call them from other functions.

let myMap = new Map()

Then into the “read” loop we will add images for “delete” and “update,” which will be appended to each todo — a minus sign and a pencil, respectively (the images should be added to an “img” directory in /usr/share/tarantool/public). Clicking on an image will call its function. Also in this main “read” loop, we will feed the todo strings from Tarantool into our map.

//read
fetch('/read')
.then(response => response.json())
.then(data => {
   mainNode = document.getElementById('div1')
   for (const x of data) {
     let todo_div = document.createElement('div')
     let todo_text = document.createTextNode(x[1])

     let todo_img = document.createElement('img')
     todo_img.setAttribute(‘style’, ‘height: 15px; width: 15px;’)
     todo_img.setAttribute('src', 'img/minus-circle.jpg')
     todo_img.setAttribute('onclick', "deleted('" + x[0] + "');")

     let todo_img2 = document.createElement('img')
     todo_img2.setAttribute(‘style’, ‘height: 15px; width: 15px;’)
     todo_img2.setAttribute('src', 'img/pencil.png')
     todo_img2.setAttribute('onclick', "updated('" + x[0] + "');")

     myMap.set(x[0], x[1])

     todo_div.append(todo_text, todo_img, todo_img2)
     mainNode.appendChild(todo_div)
    }
}).catch((err) => {          
   console.log(err)
})

Next, we will create our “deleted” and “updated” functions, starting with the former.

function deleted(delid){
  let url = '/deleted/' + delid
  fetch(url, {
    method: 'GET',
  }).then((response) => {
     location.reload()
  }).catch((err) => { 
     console.log(err)
  })
}

This function is quite simple: it accepts the id to be deleted from the image’s attribute, appends it to the “/deleted” backend route, and then sends it to Tarantool.

The “updated” function is a bit more complicated. When a pencil image is clicked, first it uses the todo’s id to look up its existing string in the global map, and then it attaches that string to the “update” box in the HTML. Once a fix is typed into the box and submitted, it posts the new value to Tarantool along with the id, so that Tarantool knows which tuple to update.

function updated(updateid) { 
  //attach existing todo string to form
  let existingstring = myMap.get(parseInt(updateid))
  let todoname_edit = document.getElementById(‘todoname_edit’)
  todoname_edit.value = existingstring

  //post new todo string and todo id to Tarantool
  let editatodo = document.getElementById(‘editatodo’)
  editatodo.addEventListener('submit', function(event){
    event.preventDefault()
    let data = new URLSearchParams()
    data.append('todoname_edit', todoname_edit.value)
    data.append('todovalue', updateid)
    fetch('/updated', {
      method: 'POST',
      body: data
    }).then((response) => {
      location.reload()
    }).catch((err) => { 
      console.log(err)
    })
  })
}

Well, that completes our Tarantool CRUD exercise. I hope that you have gained a sense of Tarantool’s simplicity and effectiveness as a solution, as well as the variety of programming choices it extends. To learn more about Tarantool functionality, please see these articles and tutorials.

Monitor application stability with Bugsnag to decide if your engineering team should be building new features on your roadmap or fixing bugs to stabilize your application.Try it free.

Topics:
crud ,tarantool ,web dev ,full-stack development

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}