How to integrate backbone.sync with jstorage? - javascript

I'm a newbie javascript developer (first post here!) and been recently trying to play with backbone.sync. I've been reading through the todo example and notice that it uses backbone-localstorage. My feeling is that backbone-localstorage was just a quick implementation that the author used for demo purposes. I also noticed that the keys are randomly generated, whereas I would like something that would allow me to name my own key values.
I've been looking at jstorage (www.jstorage.info), and would really appreciate some pointers (preferably with code samples) on how to integrate it with backbone.js. I imagine backbone.sync would need to be overriden somehow as is done in backbone-localstorage.
Alternatively, what localStorage plugin/wrapper would you recommend, and how would it integrate with backbone?
Thanks for help in advance.

My feeling is that backbone-localstorage was just a quick implementation that the author used for demo purposes.
Exactly right. I'd say that the implementation is fine for most things, but what support you can get for it is probably minimal.
I also noticed that the keys are randomly generated, whereas I would like something that would allow me to name my own key values.
This isn't really correct. I assume you are referring to this:
// Add a model, giving it a (hopefully)-unique GUID, if it doesn't already
// have an id of it's own.
create: function(model) {
if (!model.id) model.id = model.attributes.id = guid();
this.data[model.id] = model;
this.save();
return model;
}
Here, what's happening is that when a create is called on a model, it tries to determine if an id has been set on the model, and if no such id is provided, then the guid function is used to build one. This isn't setting a key randomly, it's fulfilling the requirement that every saved model should have an id (by assigining a random one).
Modifying the backbone-localstorage.js code should be fairly trivial. Let's look at the store constructor as an example
Before:
var Store = function(name) {
this.name = name;
var store = localStorage.getItem(this.name);
this.data = (store && JSON.parse(store)) || {};
};
The only thing we need to update here is the call to localStorage:
After:
var Store = function(name) {
this.name = name;
//Notice here, that jStorage gives us the option to define a default.
var store = $.jStorage.get(this.name, {});
this.data = store;
};
Similarly simple is the save function:
Before:
save: function() {
localStorage.setItem(this.name, JSON.stringify(this.data));
}
again, simply update the call to localStorage:
After:
save: function() {
$.jStorage.set(this.name, this.data);
}
Update: jStorage handles all the JSON.stringify, and JSON.parse for you, so I've updated the above code to reflect that.
Easy peasy, right!
Anyways, this is a great exercise, and I wish you the best of luck. I hope that I've been able to help you out.
P.s. One thing that bothers me about the localStorage plugin is that it uses model.attributes.xxx, where it's better to use model.get("xxx"). This way, if they ever change the internals of model change, your code won't break.
P.p.s. as far as how to generate guids, and weather a random guid is appropriate for you, depends upon your domain. With the TODO example, there is no backing database to sync with, so any old guid would do the trick, but in many other cases, you may be using html5 storage to create an offline version of your app, so id's need to be compatable with the db. In these cases, using a random guid is probably not that great an idea, but the one provided by the backbone-localstorage plugin is designed so that it isn't likely to collide with your db's actual id's, so it's not _that bad. There isn't really a right answer here, so do what makes sense for your domain.

You should probably look first at the local storage plugin that backbone.js provides. There are plenty of code samples that should give you an idea of how you would swap in jstorage as the underlying storage mechanism. See it here:
backbone-localstorage.js

Related

How can I apply Storage methods to a JS object?

I would like to be able to call the same methods of Storage { } to JS Objects { }.
These are particulary : element.key(index) and element.length.
I first though maybe we could do something as simple as var NoBrowserBasedStorage = localStorage; but it seems that it won't work, and localStorage will be used in parallel. The idea is to have a custom Object that is not at all based on the Browser, but still work as fast, as well and as if it was a localStorage.
Additional sub question, which is faster? Object {} or Storage {}?

Domain Driven Design in Node.js Application

TL; DR;
I'm looking for trite example of DDD node.js application.
Hi,
I'm going to create node application. I wonder that I can not find any example of application with business logic separated in domain.
OK, there are some examples like:
https://github.com/adrai/node-cqrs-domain - but this is whole CQRS with event sourcing implementation.
My idea is to do that like that:
//domain/book.js
function Book(title, author)
{
this._title = title;
this._author = author;
}
// domain methods ...
//infrastructure/persistance/repository/book-repository.js
function BookRepository()
{}
BookRepository.prototype.save(book)
{
var bookModel = mappers.mapToOrm(book);
return bookModel.save();
}
// [...] get, getAll, getNextId
//infrastructure/persistance/orm/book.js
//using http://bookshelfjs.org/
var Book = bookshelf.Model.extend({
tableName: 'books'
});
//infrastructure/mappers/book-mapper.js
function mapToOrm(book) {
//mapping [...]
return new persistance.Book();
}
function mapToDomain(domain) {
//mapping [...]
return new domain.Book();
}
but on the other hand I've never seen any similar solution (with domain model, orm model, repository and mappers). Am I thinking in the right way? Maybe there is no reason to separate business logic in domain in node.js applications. If so, why? If not, can you send me an example of DDD implementation or improve my code?
[2017/01/13]
I've created sample application in TypeScript. For now without repositories and not much services. Issues and pull requests are welcome.
https://github.com/dawiddominiak/ddd-typescript-bin-packing-problem-solution
I'm very new to Node.js world.
But I believe if you do your work using TypeScript with Node you can force most of DDD principles to be used.
The problem "and advantage in the same time" in node.js that there aren't so restrictions like we have in OOP languages like C# or Java. and this freedom "and messy" of JavaScript making create robust complex DomainModel and Business logic very hard
I'm looking to do the same thing at the moment, and I'm coming from the Ruby world. So, let me do 2 things:
Point you to the best Ruby implementation I've seen of Domain-Driven Design I have found, Hanami: http://hanamirb.org/guides/models/overview/ which you could use as a reference.
Discuss what I'm finding (literally right now, as I type) to attempt to find the analogs in Node.
I've found this page: https://github.com/sindresorhus/awesome-nodejs
which catalogs a ton of high-quality / high-popularity Node packages.
The first thing is, we need something that is going to do validation and schema construction for our Domain Models. Just looking at the first entry in the data validation section, Joi seems to be a decent choice for that:
https://github.com/hapijs/joi
For Persistence of the domain objects, I'm just setting up a stub object, borrowing from Hanami's interface:
var repo = {
find: function(entity_name, id) {
// - Fetch an entity from the collection by its ID
},
create: function(entity_name, data) {
// – Create a record for the given data and return an entity
},
update: function(entity_name, id, data) {
// – Update the record corresponding to the id and return the updated entity
},
delete: function(entity_name, id) {
// – Delete the record corresponding to the given entity
},
all: function(entity_name) {
// - Fetch all the entities from the collection
},
query: function(entity_name, query_object) {
},
first: function(entity_name) {
// - Fetch the first entity from the collection
},
last: function(entity_name) {
// - Fetch the last entity from the collection
},
clear: function(entity_name) {
// - Delete all the records from the collection
}
}
module.exports = repo
whether you choose to use Bookshelf, Sequelize, or even the LoopBack framework, you can code an object that is going to fit the above interface that then does the dirty work of integrating with those frameworks.
If I were to try different ORM's, I would create a different repo object for each of the above. Notice that as I've written it, the repo is a singleton that is aware of different entities and how to persist them. In many cases, this will no doubt delegate to different repository objects on a per-entity basis. However, that might not always be true. a simple in-memory repo, could just have an array of objects for each entity.
That leaves Services/Interactors - The functions/classes that actually do work. These are easy - they are the ones that take a domain object, perform some business logic, and in the CRUD cases, make a call out to the Repository. A probably-syntactically-wrong example:
const repository = require('./myFileRepository')
function createBook(bookEntity) {
if(bookEntity.valid?) {
repository.create('book', bookEntity)
return true
}
else {
return { error: 'book not valid' }
}
}
module.exports = createBook
for the Service functions, I just today learned about Node Machines, and they seem like a really smart idea: http://node-machine.org
they seem to be a JS-attempt at monads + documentation. so I'm considering writing them up like that.
anyway, given it's been a year since your post, you've probably moved on. hope this helps you / the community!
Many would argue that JavaScript is NOT well suited to modeling a complex problem into a domain model and then into code. That's especially the case if the domain is in business, industry and commerce, rather than in computer or data science.
I'm not saying one can't create a domain model in JavaScript. Just like one could create one in C. But does that mean one should?
The example you give uses some terminology in domain-driven design, but misses the whole purpose and ethos of applying it.

restangular save ignores changes to restangular object

I'm trying to call save on a restangularized object, but the save method is completely ignoring any changes made to the object, it seems to have bound the original unmodified object.
When I run this in the debugger I see that when my saveSkill method (see below) is entered right before I call save on it the skill object will reflect the changes I made to it's name and description fields. If I then do a "step into" I go into Restangular.save method. However, the 'this' variable within the restangular.save method has my old skill, with the name and description equal to whatever they were when loaded. It's ignoring the changes I made to my skill.
The only way I could see this happening is if someone called bind on the save, though I can't why rectangular would do that? My only guess is it's due to my calling $object, but I can't find much in way of documentation to confirm this.
I'm afraid I can't copy and paste, all my code examples are typed by hand so forgive any obvious syntax issues as typos. I don't know who much I need to describe so here is the shortened version, I can retype more if needed:
state('skill.detail', {
url: '/:id',
data: {pageTitle: 'Skill Detail'},
tempalte: 'template.tpl.html'
controller: 'SkillFormController',
resolve: {
isCreate: (function(){ return false;},
skill: function(SkillService, $stateParams){
return SkillService.get($stateParams.id, {"$expand": "people"}).$object;
},
});
my SkillService looks like this:
angular.module('project.skill').('SkillService', ['Restangular, function(Retangular) {
var route="skills";
var SkillService= Restangular.all(route);
SkillService.restangularize= function(element, parent) {
var skill=Restangular.restangluarizeElement(parent, elment, route);
return skill;
};
return SkillService;
}];
Inside of my template.tpl.html I have your standard text boxes bound to name and description, and a save button. The save button calls saveSkill(skill) of my SkillFormController which looks like this:
$scope.saveSkill=function(skill) {
skill.save().then(function returnedSkill) {
toaster.pop('success', "YES!", returnedSkill.name + " saved.");
...(other irrelevant stuff)
};
If it matters I have an addElementTransformer hook that runs a method calling skilll.addRestangularMethod() to add a getPeople method to all skill objects. I don't include the code since I doubt it's relevant, but if needed to I can elaborate on it.
I got this to work, though I honestly still don't know entirely why it works I know the fix I used.
First, as stated in comments restangular does bind all of it's methods to the original restangularizedObject. This usually works since it's simply aliasing the restangularied object, so long as you use that object your modifications will work.
This can be an issue with Restangular.copy() vs angular.copy. Restangualar.copy() makes sure to restangularize the copied object properly, rebinding restangualr methods to the new copy objects. If you call only Angular.copy() instead of Restangualar.copy() you will get results like mine above.
However, I was not doing any copy of the object (okay, I saved a master copy to revert to if cancel was hit, but that used Restangular.copy() and besides which wasn't being used in my simple save scenario).
As far as I can tell my problem was using the .$object call on the restangular promise. I walked through restangular enough to see it was doing some extra logic restangularizing methods after a promise returns, but I didn't get to the point of following the $object's logic. However, replacing the $object call with a then() function that did nothing but save the returned result has fixed my issues. If someone can explain how I would love to update this question, but I can't justify using work time to try to further hunt down a fixed problem even if I really would like to understand the cause better.

Adding Models to Backbone.js Collection Silently Fails

I am implementing a Blog Engine as a learning exercise for a new job. I have a Backbone.js Collection class called BlogList that is composed of BlogModel objects (a BlogModel is a single post to a blog). I have a masterBlogList that keeps all blog posts in memory for the lifetime of the application (I realize this is not a realistic design, but it is part of the spec).
I have chosen to use masterBlogList to hold the canonical state of the application. All new posts, edits, etc. are persisted to the database (MongoDB) as well as masterBlogList. When I want to display a subset of the posts in masterBlogList, I copy them into a new BlogList instance and then narrow this new instance down based on search criteria. Again, I realize this might not be the best design (cloning BlogModels and BlogLists), but it is what I've got and I'd prefer not to rework it.
The problem is that copying one BlogList to another is not working. Even when the source list is non-empty, the destination list always ends up being empty. I have tried to debug this every which way with no luck. Here is the relevant portion of the BlogList source code:
// BlogList
$ (function () {
App.BlogList = Backbone.Collection.extend ({
model : App.BlogModel,
url : '/blog-entries',
comparator : function (a) {
return -(new Date (a.get ('date')));
},
populateFromMemory : function (sourceList) {
// this.reset ();
var self = this;
sourceList.each (function (postModel) {
self.add(postModel);
});
var foo = new App.BlogModel();
this.add(foo);
},
(continued...)
Even the last bit regarding foo is not working. I've also tried adding a clone() of postModel and also new App.BlogModel(postModel.toJSON()).
Any help would be extremely appreciated!
Sorry to have bothered anyone :<, but I got it working. The code actually does work as written above. The problem is that my search criteria were filtering out all of the posts, so I wasn't seeing anything. End of a long day! Thanks to those who tried to help me...

Model-View-Controller in JavaScript

tl;dr: How does one implement MVC in JavaScript in a clean way?
I'm trying to implement MVC in JavaScript. I have googled and reorganized with my code countless times but have not found a suitable solution. (The code just doesn't "feel right".)
Here's how I'm going about it right now. It's incredibly complicated and is a pain to work with (but still better than the pile of code I had before). It has ugly workarounds that sort of defeat the purpose of MVC.
And behold, the mess, if you're really brave:
// Create a "main model"
var main = Model0();
function Model0() {
// Create an associated view and store its methods in "view"
var view = View0();
// Create a submodel and pass it a function
// that will "subviewify" the submodel's view
var model1 = Model1(function (subview) {
view.subviewify(subview);
});
// Return model methods that can be used by
// the controller (the onchange handlers)
return {
'updateModel1': function (newValue) {
model1.update(newValue);
}
};
}
function Model1(makeSubView) {
var info = '';
// Make an associated view and attach the view
// to the parent view using the passed function
var view = View1();
makeSubView(view.__view); // Dirty dirty
// Return model methods that can be used by
// the parent model (and so the controller)
return {
'update': function (newValue) {
info = newValue;
// Notify the view of the new information
view.events.value(info);
}
};
}
function View0() {
var thing = document.getElementById('theDiv');
var input = document.getElementById('theInput');
// This is the "controller", bear with me
input.onchange = function () {
// Ugly, uses a global to contact the model
main.updateModel1(this.value);
};
return {
'events': {},
// Adds a subview to this view.
'subviewify': function (subview) {
thing.appendChild(subview);
}
};
}
// This is a subview.
function View1() {
var element = document.createElement('div');
return {
'events': {
// When the value changes this is
// called so the view can be updated
'value': function (newValue) {
element.innerHTML = newValue;
}
},
// ..Expose the DOM representation of the subview
// so it can be attached to a parent view
'__view': element
};
}
How does one implement MVC in JavaScript in a cleaner way? How can I improve this system? Or is this the completely wrong way to go, should I follow another pattern?
There are at least a couple of established and usable MVC frameworks for JavaScript JavaScriptMVC and pureMVC. There are probably more. I've used JavaScriptMVC for browser based and Air apps and keep coming back to it - it has its problems but I've found it to be quite useful.
There are other solutions too, have a look at Sammy, a new thing I've heard good things about. I haven't used myself but intend to try soon. I don't know enough about it to describe it properly, but to me it seems like a front controller which works on routes, a templating system and ReSTful data stores. I'm not sure if it is MVC but has similar ingredients.
I have to disagree with mway's answer. MVC may be a bit diferent to implement in JavaScript but its benefits are very important to organising this mess. The design patterns usually associated with OO languages don't go out the window just because js isn't class based.
I would say that MVC is more suitable for JavaScript apps than for request based (server side) applications. Those objects can hang around for a while in a one page JavaScript app - minutes if not hours - and having a well organised way of organising their interaction will make your code much more robust and easy to deal with. There are books on the subject.
A couple of other points regarding the code you posted.
The view objects have responsibility for applying event listeners to DOM elements. This is the controller's job. The view just renders the HTML - the controller listens for the events and acts accordingly.
Your models seem to know your views. The model layer should have minimal knowledge of the view layer (perhaps being registered as observers). Keep your model clean and to the point, I mean the business point - business logic. In js apps you may just be proxying for a sever side model layer but it is important for your sanity to keep your model to the business logic and nothing else. Application logic is the controllers job
To be honest, MVC isn't well-suited for Javascript. It can support the basic fundamentals of the design, sure - you can create pseudoclasses to act as controllers or models, support basic inheritance, and you can have it manipulate or create any number of DOM elements, but there's a price that you pay for that - in overhead, accessibility, and usability.
In my opinion, I consider Javascript more of an augmentation - the KISS mentality exists for a good reason. If you're interested in better ways to organize your code, there's always the option of packaging related functionality into modules (sic) and abstracting out portions as appropriate. For example, creating a factory to do more complex AJAX request management, or a pseudoclass to handle processing of similar types of data. Using a standard base function for controllers, another for models, etc, as prototypes for new instances of those objects can accomplish similar functionality... but again, it's sort of going against the grain of Javascript.
However, if you're stuck on the MVC idea just for the sake of structure, consider something like the following:
;(function(window, $) {
/**
* Event Object
* A quick description goes here.
**/
var Events = window.Events = {
'bindTrackables': function() {
$('a.trackable').live('click', function() {
if(!_gaq)
_gaq = [];
_gaq.push(['_trackPageview', '/ajax/foobar']);
});
},
'bindSomeEvent': function() {
// etc
}
};
/**
* Data Cache
* I'll need to remember stuff later, so I store it here
**/
var Cache = window.Cache = {
'data': {},
'store': function(key, value) {
Cache.data[key] = value;
},
'fetch': function(key) {
return Cache.data[key];
}
};
/**
* Request Object
* Stores native AJAX requests for later use
**/
var Request = window.Request = {
'current_requests': [],
'send': function(url, type, data, callback) {
Request.current_requests.push($.ajax({
'url': url,
'type': type,
'data': data,
'callback': callback
}));
},
}
// add some private logic here
})(window, jQuery);
It's extremely basic, but you get the idea. Modular code is key... in JS, this is more important than forcing your application (or the language) to fit a certain style.

Categories

Resources