Thinky — How to Add Methods to a Model and Documents

We’ve touched Thinky last week and showed you how to query documents by fields of a nested object. This week, we’re continuing on Thinky with another post showing you how to extend your Model definition by adding custom methods.

Before diving into the details, have a look at previously published Thinky posts:

Thinky Series Overview

Define a Model in Thinky

Due to the fact that you’re searching for ways to extend an existing model, you’re already familiar with the definition using Thinky. Nonetheless, let’s shortly recap how to define a model to have the same context on what we’re talking about.

There’re multiple ways to import the thinky dependency to your project. We propose to follow the advice on how to import Thinky correctly given within its documentation. The code snippet below outlines a basic User model having three properties: id, username, password. Further, the id property will be initialized with a default value (UUID).

var thinky = require('./utils/thinky')  
var r = thinky.r  
var type = thinky.type  
var User

User = thinky.createModel('User', {  
  id: type.string().default(r.uuid()),
  username: type.string(),
  password: type.string()
})

Up to this point, you should be familiar with the definition of a Thinky model. In the following section, we’ll extend our User model by adding a new method.

Add Methods to Model

Thinky allows us to extend a model definition by adding methods that are available for each document of the related model type. The basic approach to add custom methods is to use Thinky’s define() function of your Model:

Model.define('methodName', function() {})  

Using define() will save the method and makes it available for each document based on the given model. Precisely, you can add document specific functionality in a model method and the implementation will be available for every document.

The following code block illustrates the comparePassword functionality that compares a candidate password with the user's encrypted password leveraging bcrypt. Actually, we’re wrapping the bcrypt call into a promise (because we’re huge promises fanboys :)). Of course, you don’t need to rely on promises within your implementation.

var bcrypt = require('bcrypt')  
var when = require('when')  
var Boom = require('boom')

User.define('comparePassword', function (candidatePassword) {  
  var self = this

  return when.promise(function(resolve, reject) {
    bcrypt.compare(candidatePassword, self.password, function (err, isMatch) {
      if (isMatch) {
        return resolve(self)
      }

      return reject(Boom.badRequest('Passwords does not match.'))
    })
  })
})

If the given candidate matches the user’s password, the comparePassword method returns the user. If passwords don’t match, we’ll return a rejected promise that includes an error object having the message that passwords don’t match.

Outlook

Within this guide, you’ve learned how to extend your Thinky model to add custom methods to each of the related documents. We’ve illustrated a model extension by implementing a compare password functionality to check whether the current user’s password matches the candidate one.

Next week, we’ll again continue on Thinky and show you how to sort joined documents.

If you feel there’s something missing or needs further explanation, please let us know within the comments below or shoot us a message on Twitter: @futurestud_io.

Make it rock & enjoy coding!


Additional Resources

Explore the Library

Find interesting tutorials and solutions for your problems.