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

Following your example I'm not sure if 'Book' should point to the model #49

Open
DanielTate opened this issue Nov 23, 2015 · 5 comments

Comments

@DanielTate
Copy link

Uncaught TypeError: relatedModel "Book" is neither a reference to a JJRelationalModel nor a string referring to an object in the global oject

var Author = Backbone.JJRelationalModel.extend({
    storeIdentifier: 'Author',
    relations: [
        {
            type: 'has_many',
            relatedModel: 'Book', <------ should this be a string
            key: 'books',
            reverseKey: 'author',
            collectionType: 'Books', <------- this also
            includeInJSON: ['id', 'title']
        }
    ]
});

var Author = Backbone.JJRelationalModel.extend({
    storeIdentifier: 'Author',
    relations: [
        {
            type: 'has_many',
            relatedModel: BookModel, <------ or should it point to the model
            key: 'books',
            reverseKey: 'author',
            collectionType: 'Books', <------- this also
            includeInJSON: ['id', 'title']
        }
    ]
});
@sarink
Copy link
Contributor

sarink commented Nov 23, 2015

What's your Backbone.JJStore look like when this fails?

@DanielTate
Copy link
Author

I'm not sure about Backbone.JJStore. I have managed to get it to work but I can't use them in external AMD modules I am having to use the them inline which is not ideal. I assume this is a scope issue but I haven't figured it out yet.

It works inline, not from different AMD modules pulling into one file for use.

@sarink
Copy link
Contributor

sarink commented Nov 23, 2015

I think you'll have to require() all your collections in the very beginning
of the app before anything else happens. At the end of each collection
module make sure to register it with the store by calling
registerCollectionType with the collection's name.

You can see why AMD is not officially supported :)

Are you actually going to asynchronously load all modules in production? If
not, now may be the time to switch to commonjs modules, if you can.
Otherwise, the above solution should work.

I'll try to get up a working code example of this later if I can.
On Nov 22, 2015 8:35 PM, "Daniel" [email protected] wrote:

I'm not sure about Backbone.JJStore. I have managed to get it to work but
I can't use them in external AMD modules I am having to use the them inline
which is not ideal. I assume this is a scope issue but I haven't figured it
out yet.

It works inline, not from different AMD modules pulling into one file for
use.


Reply to this email directly or view it on GitHub
#49 (comment)
.

@DanielTate
Copy link
Author

Thanks @sarink I appreciate the example.

I think AMD isn't hard to get working you just need to Shim the plugin if you document this I think it will be enough, there isn't a huge need for more but it would be nice.

@sarink
Copy link
Contributor

sarink commented Nov 23, 2015

Try this

requirejs.config.js

/* requirejs.config.js */

requirejs.config({
    paths: {
        "jquery": "vendor/jquery",
        "underscore": "vendor/underscore",
        "backbone": "vendor/backbone",
        "backbone.JJRelational: "vendor/backbone.JJRelational",
        "my-backbone": "js/my-backbone.js" // this is what you should require() when you want backbone
    },
    shim: {
        "jquery": {
            exports: "$"
        },
        "underscore": {
            exports: "_"
        },
        "backbone": {
            deps: ["jquery", "underscore"],
            exports: "Backbone"
        },
        "backbone.JJRelational": {
            deps: ["backbone"],
            exports: "Backbone"
        }
    }
});

my-backbone.js

/* my-backbone.js */

// use this file to include JJ and also apply any global backbone prototype overrides or punches you may have
// (every backbone app has a few)

define(["underscore", "backbone", "backbone.JJRelational"],
function(_, Backbone, JJRelational) {
    "use strict";

    // Never search `window` for related models
    Backbone.JJStore.removeModelScope(window);

    return Backbone;
});

application.js

/* application.js */

// require all collections in the beginning of the app so that they are all registered with the global JJStore
define(["collections/BookList", "collections/AuthorList"],
function(BookList, AuthorList) {
    ...
});

collections/BookList.js

/* BookList.js */

define(["underscore", "my-backbone", "../models/Book"],
function(_, Backbone, Book) {
   "use strict":

    var BookList = Backbone.Collection.extend({
        model: Book
    });

    // this is important
    Backbone.JJRelational.registerCollectionTypes({BookList: BookList});

    return BookList;
});

models/Book.js

/* Book.js */

define(["underscore", "my-backbone"],
function(_, Backbone) {
    "use strict";

    var Book = Backbone.JJRelationalModel.extend({
        storeIdentifier: "Book"
    });

    // this is important
    Backbone.JJStore.addModelScope({Book: Book});

    return Book;
});

Creating a my-backbone.js is the only way I can think of doing this that doesn't feel super dishonest. Plus, it gives you a place to add the rest of your backbone overrides. I know from working with a rails api I've often had to override Backbone.ajax to include the csrf token, or duck-punch Backbone.Model.prototype.url to strip out ".json" from within the url, but then append it before returning, when working with nested routes, for example.

Although if you hate this solution, I understand why. But I think it might be as good as it's gonna get.

To be completely honest, I've not written a Backbone app in some time. React+Flux is the way to go, imo. You may get better support from using one of the more popular BB Relational libraries (although, I've tried them all, and was always met with great pain. I do have a couple of apps running in production still today with JJRelational, but you should think hard about this decision before it's too late.)

Good luck.

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