Skip to content

Model for CouchDB and Cloudant #7

@mateusnroll

Description

@mateusnroll

Models are essential to persisting data, which almost any application needs. Since ike is built on Javascript, it makes sense to focus on non-relational databases first.

The first one we're attacking is CouchDB and its super-saiyan counterpart Cloudant. Both will have a dedicated model for persisting and retrieving data.

Basic information

  • The model will be called Kubus, which is a type of couch.
  • Should, as always, drink as much as possible from Rails.
  • Smart defaults, configurable if needed.
  • Model validation and simple error handling.

Database views

Views are design documents specifically designed to retrieve information from the database.

  • Database views should all be in one folder, each one on its file. The ideal path is /app/dbviews/. There can be folders inside dbviews, but only on very specific cases.
  • Each file will be named as filename.view.js.

A view file should look like:

class SomeView extends KubusView {
    constructor() {
        this.viewName = 'someOtherName'; // Optional, default would be class name
    }

    map(doc) {
        emit(doc.id, doc.balance);
    }

    reduce(key, values, rereduce) {
        return sum(values);
    }
}

Cloudant search indexes

Search indexes should be their own file type, and reside in a separate file (but within dbviews folder). The file should be name filenmame.search.js.

A search index file should look like:

class SomeSearchIndex extends KubusSeach {
    constructor() {
        this.viewName = 'someOtherName'; // Optional, default would be class name
    }

    map(doc) {
        index('name', doc.name, {store: true});
    }
}

To query a seach index, just use the method search:

const SomeSearchIndex = require('dbviews/some.search.js');

SomeSearchIndex.search('name:john')
    .then(person => res.send(person))
    .catch(error => res.status(500).send(error));

Database models

Model superclass
Model classes are logical representations of the document, and the superclass should provide a foundation for building on top of.

class Some extends KubusModel {}

Document validation
Cloudant and CouchDB will accept any document, and it's the job of the application to ensure consistency. Having model validations will aid just that.

class Some extends KubusModel {
    constructor() {
        this.validation = {
            name: String,
            age: Integer,
            birthDate: Date,
            Something: Object,
            anotherSomething: {
                name: String,
                region: string
            }
        };

        this.validationOptions = {strict: true, stopOnFirstError: true};
    }
}

Easy document retrieval
Getting documents should be easy enough, specially when I know exactly what I'm looking for.

const Sample = require('models/sample.model.js');
Sample.get('abcf-1234-hfds').then(...);

Edit and delete documents
Editing and deleting documents should be left to the instance, which will be able to know exaclty what to do with the document and its state.

const Sample = require('models/sample.model.js');
Sample.get('abcf-1234-hfds').then(
    sample => {
        sample.name = "Something";
        return sample.save;
    },
).then(
    saveSuccess => res.status(201).send();
).catch(
    error => res.status(400).send(error);
);

Lifecycle events
It should be possible to hook into a specific lifecycle point and perform actions. Main lifecycle events we should be looking into:

  • Before validation
  • After validation
  • Before save
  • After save
  • Before update
  • After update
  • Before delete
  • After delete

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions