Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Local persistence service for cells #315

Open
kentmw opened this issue Apr 3, 2017 · 4 comments
Open

Local persistence service for cells #315

kentmw opened this issue Apr 3, 2017 · 4 comments

Comments

@kentmw
Copy link
Contributor

kentmw commented Apr 3, 2017

I'd like to persist cells to local storage and then recreate that cell later. Here's my attempt:

var Torso = require('backbone-torso');

module.exports = Torso.ServiceCell.extend({

	watch: function(cell, alias) {
		this.listenTo(cell, 'change', () => { this.saveCell(cell, alias); });
		this.saveCell(cell, alias);
	},

	stopWatching: function(cell) {
		this.stopListening(cell);
	},

	getCell: function(CellClass, alias) {
		return new CellClass(this._getData(alias));
	},

	updateCell: function(cell, alias) {
		cell.set(this._getData(alias));	
	}

	saveCell: function(cell, alias) {
		localStorage.setItem(alias, JSON.stringify(cell.toJSON()));
	},

	_getData: function(alias) {
		return JSON.parse(localStorage.getItem(alias));
	}

});
@mandragorn
Copy link
Contributor

what does localStorage.getItem('someItemThatDoesNotExist') return? I.e. what if you try to get a cell before you've called save or watch?

@kentmw
Copy link
Contributor Author

kentmw commented Apr 3, 2017

it returns null out of localstorage. It returns an empty cell if getCell is called. It doesn't change the cell if updateCell is called

@mandragorn
Copy link
Contributor

is it work having a getAndWatch method that would allow you to both get and watch the cell? I feel like that is how I'd normally want to use this - get a cell that mirrors the local storage to cover both the case of a cell that isn't saved yet and one that is.

What happens if you change the local storage via a separate tab? Is there a way to pick up those changes? Or will the 2 tabs compete?

@kentmw
Copy link
Contributor Author

kentmw commented Apr 17, 2017

This code bit by @stonecalvin was found in nexus-robot:

module.exports = Torso.Model.extend({

  /**
   * @property localStorageName {String} The unique name for this settings model, used
   *               to generate its local storage key. This property must be set to a
   *               unique value for each instance of this model.
   */
  localStorageName: 'default',

  /**
   * Generates a key that should be unique per instance of this model.
   * It has a prefix of "npsm-" (nexus-prime settings model) to ensure an extra bit of
   * collision protection.
   * @method getLocalStorageKey
   * @returns {String} the local storage key for this model instance.
   */
  getLocalStorageKey: function() {
    return 'npsm-' + this.localStorageName;
  },

  /**
   * Loads the settings data from the browser's local storage.
   * @private
   * @method _loadDataFromLocalStorage
   */
  _loadDataFromLocalStorage: function() {
    let savedModelString = localStorage.getItem(this.getLocalStorageKey());
    this.set(JSON.parse(savedModelString));
  },

  /**
   * Upserts (updates or inserts) the settings data to the browser's local storage.
   * @private
   * @method _upsertToLocalStorage
   */
  _upsertToLocalStorage: function() {
    localStorage.setItem(this.getLocalStorageKey(), JSON.stringify(this.toJSON()));
  },

  /**
   * @Override
   * @method sync
   */
  sync: function(method, model) {
    let deferred = new $.Deferred();

    switch (method) {
      case 'patch':
        // Writing to local storage shouldnt be costly, so we will defer to
        // full object updates for patch requests.
        /* falls through */
      case 'create':
        /* falls through */
      case 'update':
        model._upsertToLocalStorage();
        break;
      case 'read':
        try {
          model._loadDataFromLocalStorage();
        } catch (e) {
          // Error when occurred when loading or parsing the data from local storage
          deferred.reject(e);
          return deferred.promise();
        }
        break;
      case 'delete':
        localStorage.removeItem(model.getLocalStorageKey());
        break;
      default:
        deferred.reject(Error('Unknown sync method requested: [' + method + ']'));
        return deferred.promise();
    }

    deferred.resolve('Successfully synced with local storage object');
    return deferred.promise();
  }
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants