2

I'm building a hierarchical data model out of some flat data using backbone and running into a problem when i'm trying to use a relational model. The output of the below code looks like this:

"D"
    "B"
        "C"
        "F"
    "G"
        "A"

where each letter corresponds to an id in a related model. When I add the association into the TreeNode model to form the relation, the tree stops iterating and I only get the first set of results (D > B > C) and not (D > B > F) or (D > G > A) as I wanted. Here is the output when I add the relations:

{"label":"Fred","language":"en","id":"D","datatype":"number"}
    {"label":"is friends with","language":"en","id":"B","datatype":"text"}
        {"label":"Violet","language":"en","id":"C","datatype":"text"}

I'm new to backbone relational and not sure if i'm doing this correctly. Here is the sample code (i paired it down as much as possible and noted the problem area with HERE IS THE PROBLEM)

Thanks in advance!!!

<!DOCTYPE html>
<html>
<head>
    <title>Relational Graph</title>
    <meta charset="utf-8" />
    <script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.1/underscore-min.js"></script>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.2/backbone-min.js"></script>
    <script src="js/backbone.marionette.js"></script>
    <script src="js/backbone.relational.js"></script>
</head>
<body>

<div id="model"></div>

<script>

$(document).ready(function(){

    MainApp = new Backbone.Marionette.Application();
    MainApp.addRegions({treeRegion: "#model"});
    MainApp.addInitializer(function(options){
        var trunk = things.search({id: "D"}).first();
        var tree = new TreeNodeCollection(graphify(options.relationships, trunk));
        var treeView = new TreeRoot({collection: tree});
        this.treeRegion.show(treeView);
    });

    TreeNode = Backbone.RelationalModel.extend({
        initialize: function(){
            var nodes = this.get("nodes");
            if (nodes){
                this.nodes = new TreeNodeCollection(nodes);
                this.unset("nodes");
            }
        },
        render: function(){
            var that = this;
            TemplateManager.get(this.template, function(template){
                var html = $(template).tmpl();
                that.$el.html(html);
            });
            return this;
        }
        // !!! HERE IS THE PROBLEM - when I add this line, it stops looping through the tree :(
        //, relations: [{type: Backbone.HasOne, key: 'id', relatedModel: "Thing"}]
    });

    TreeNodeCollection = Backbone.Collection.extend({model: TreeNode});

    TreeView = Backbone.Marionette.CompositeView.extend({
        template: "#node-template",
        tagName: "ul",
        initialize: function(){
            this.collection = this.model.nodes;
        },
        appendHtml: function(collectionView, itemView){
            collectionView.$("li:first").append(itemView.el);
        }
    });

    TreeRoot = Backbone.Marionette.CollectionView.extend({itemView: TreeView});

    Thing = Backbone.RelationalModel.extend();
    Things = Backbone.Collection.extend({
        model: Thing,
        search: function(opts){
            return new Things(this.where(opts));
        }
    });

    Relationship = Backbone.RelationalModel.extend({
        relations: [
            {type: Backbone.HasOne, key: 's', relatedModel: Thing},
            {type: Backbone.HasOne, key: 'p', relatedModel: Thing},
            {type: Backbone.HasOne, key: 'o', relatedModel: Thing}
        ]
    });

    Relationships = Backbone.Collection.extend({
        model: Relationship,
        search: function(opts){
            return new Relationships(this.where(opts));
        }
    });

    things = new Things([
        new Thing({label: 'Sam', language: 'en', id: 'A', datatype: 'text'}),
        new Thing({label: 'Fred', language: 'en', id: 'D', datatype: 'number'}),
        new Thing({label: 'Jake', language: 'en', id: 'E', datatype: 'text'}),
        new Thing({label: 'Sally', language: 'en', id: 'F', datatype: 'number'}),
        new Thing({label: 'is friends with', language: 'en', id: 'B', datatype: 'text'}),
        new Thing({label: 'is working with', language: 'en', id: 'G', datatype: 'text'}),
        new Thing({label: 'Violet', language: 'en', id: 'C', datatype: 'text'})
    ]);

    relationships = new Relationships([
        new Relationship({s: "A", p: "B", o: "C"}),
        new Relationship({s: "A", p: "B", o: "D"}),
        new Relationship({s: "A", p: "B", o: "E"}),
        new Relationship({s: "A", p: "B", o: "F"}),
        new Relationship({s: "D", p: "B", o: "C"}),
        new Relationship({s: "D", p: "B", o: "F"}),
        new Relationship({s: "A", p: "G", o: "F"}),
        new Relationship({s: "D", p: "G", o: "A"})
    ]);

    MainApp.start({things: things, relationships: relationships});

    function arrUnique(field, arr){
        var all = [];
        arr.each(function(item){
            all.push(item.get(field).get('id'));
        });
        return _.uniq(all);
    }

    function graphify(arr, obj){
        var graphNew = [];
        var uniqueSubjects = arrUnique("s", arr.search({s: obj}));
        for (var i=0; i<uniqueSubjects.length; i++){

            var subject = uniqueSubjects[i];
            var newSubject = {id: subject};
            var subNodes = [];
            var uniquePredicates = arrUnique("p", arr.search({s: obj}));

            for (var j=0; j<uniquePredicates.length; j++){
                var predicate = uniquePredicates[j];
                var newPredicate = {id: predicate};
                var relatedObjects = [];
                arr.each(function(o){
                    if (o.get("s").get("id") == subject && o.get("p").get("id") == predicate){
                        relatedObjects.push({id: o.get("o").get("id")});
                    }
                });

                newPredicate.nodes = relatedObjects;
                subNodes.push(newPredicate);
            }

            newSubject.nodes = subNodes;
            graphNew.push(newSubject);
        }
        return graphNew;
    }

});

</script>

<script type="text/template" id="node-template">
    <li><label><%= JSON.stringify(id) %></label></li>
</script>

</body>
</html>
Devin McQueeney
  • 1,277
  • 2
  • 14
  • 31

0 Answers0