Search code examples
javascriptangularjsormcircular-reference

Taming hasMany/belongsToOne circular reference in client side ORM


I'm using angular in my case but it's a general question as well. Also I'm aware of other front end ORM solutions like js-data and restacular but that's a different story.

Given a People collection made of several Person instances:

[
    { name: "Bob" },
    { name: "Dave" },
    { name: "Sarah" }
]

How can each Person instance have the ability (method) to push a new instance of itself with inherited properties into its parent collection? Let's say a Person instance looks like this:

{
    name: "Bob",
    parent: [ /* circular reference to collection */ ],
    extend: function(attrs) { /* returns new object */ },
    create: function(attrs) {
        var self = this;
        //call factory method to create object
        var person = self.extend(attrs);
        //some http call to persist to backend
        .then(function() {
            //push new instance to parent so it's rendered in the view model
            self.parent.push(person);
        });
    }
}

Maybe this method of encapsulation is bad...I'm not sure. I made a plnkr that attempts to create a directive that inherits a JSON stringified circular reference (not good) via two way binding.

directive

angular
    .module("app", [])
    .directive("appDirective", function() {
        return {
            scope: { data: "=appDirective" },
            bindToController: true,
            controllerAs: "vm"
        };
    });

html

<div app-directive="{foo: 'bar', info: vm.info}">{{vm.data}}</div>

inside parent controller

this.info = {};
//setup circular reference
this.info.info = this.info

How can I retain the luxury of circular references in my ORM while getting around the circular JSON stringify problem?


Solution

  • You'll need to write your own stringify, pulling out the objects to a reference array and replacing them with the reference array key. Or you can use the jsog library that I have found useful

    also, this StackOverflow answer if you are interested in trying to do it yourself