DAO - Data Access Object

DAO is a universal interface to a collection of data.

FOAM includes implementations of the DAO interface for many different storage platforms. A full list is available here. Some highlights:

  • In the browser: IndexedDB and LocalStorage.
  • In Node.js: MongoDB, SQLite, JSON and XML files.
  • In memory everywhere: MDAO – a blazing fast, query optimizing, in-memory DAO.

The real magic: decoration

A universal interface is good for hiding the details of different storage platforms, but the real trick is that we can write decorators that add extra behavior to any underlying DAO.

FOAM comes with many of these DAO decorators. They add various caching strategies, logging and performance measurement, perform schema migrations transparently, and much more.

This design separates concerns: the underlying DAOs talking to real databases don’t need to worry about caching, logging, or anything else. They can stay focused on their real job – storing data in a backend.

Saving our data

Our app has so far been defaulting to an MDAO for storing our Todos. Since MDAO only stores data in memory, the data has disappeared on each refresh. Let’s make it persistent, by storing it in LocalStorage.

Edit PROJECT/js/com/todo/TodoApp.js.

First, add foam.dao.EasyDAO to the requires:

requires: [
  'com.todo.model.Todo',
  'foam.dao.EasyDAO',
],

Then remove the model property, and instead add data property with a factory, like so:

CLASS({
  package: 'com.todo',
  name: 'TodoApp',
  extends: 'foam.browser.u2.BrowserController',
  requires: [
    'com.todo.model.Todo',
    'foam.dao.EasyDAO',
  ],

  properties: [
    {
      name: 'data',
      factory: function() {
        return this.EasyDAO.create({
          model: this.Todo,
          daoType: 'LOCAL',
          cache: true,
          seqNo: true
        });
      }
    },
  ]
});

Try it out, and you’ll see that we’re now saving the data between reloads.

EasyDAO

What’s going on here? Well, EasyDAO is a helper for building a decorated DAO.

You can of course assemble a DAO by hand, but certain patterns are common enough that we captured them in EasyDAO. Here we specify the model (this.Todo again), daoType: 'LOCAL' (meaning LocalStorage), cache: true and seqNo: true.

The result is a DAO which ultimately uses LocalStorage, but is fully cached in memory, and automatically sets id on any newly inserted objects to the next unused value.

Instead of specifying the model for our BrowserController and letting it make up a DAO, we’re instead supplying the DAO directly as BrowserController.data.

Next

We’re getting there! Next, we’ll customize our list rows to make them more useful in Part 5: Custom views.