Git Product home page Git Product logo

Comments (6)

claudioc avatar claudioc commented on August 25, 2024

👍

from ampersand-model.

dazld avatar dazld commented on August 25, 2024

We also don't need to propagate user data down into randomly required models and collections,
something quite painful to do in event-loop based async programming on node.

This is the really killer requirement!

from ampersand-model.

latentflip avatar latentflip commented on August 25, 2024

Hey @TimBeyer! There's a lot here, that I'm trying to get my head around, so bear with me if I'm misunderstanding you.

sync aka ampersand-sync is accessed from the closure scope in ampersand-model

This is true, however, it's only ever accessed by the sync method, so if you want to not use ampersand-sync, and instead use something else, there's no reason you can't do:

var BaseModel = AmpersandModel.extend({
    sync: function(method, model, options) {
      //do whatever you want in here
    }
});

If that's not enough, and you really don't want any of the sync stuff from ampersand-model, have you seen ampersand-state](https://github.com/AmpersandJS/ampersand-state)? It's basically ampersand-model but without any of the restful syncing stuff - which sounds like what you want, I think?

As to your original problem of how to handle user-specific tokens, we solve this at &yet by using the ajaxConfig options, and setting a base model up like this, as per ajaxConfig docs.

//some global-ish object to store your accessToken in:
app.me.accessToken = "{wherever you got the access token}";

var BaseModel = AmpersandModel.extend({
    ajaxConfig: function () {
        return { 
            headers: {
                "Authorization": app.me.accessToken
            }
        }
    }
});

But it's quite possible I've misunderstood what you're trying to do?

from ampersand-model.

TimBeyer avatar TimBeyer commented on August 25, 2024

So, let me try to explain:

I wanted to do exactly what you proposed:
use the raw ampersand-state, add a url method to it and then use external sync methods.

To re-use your code for fetch, save and destroy, my plan was to just do

var Model = require('ampersand-model');
var fetch = Model.prototype.fetch;

var fetchState = function (state) {
    return fetch.call(state);
};

But then it also needs this.sync, so I cannot just call it on state alone.
I'd need an object that delegates to the state methods and properties (state.set, state.parse, state.trigger etc etc) for everything except sync, which needs to be overridden.

Basically what's really in the way is Model.prototype.sync, which directly delegates to sync - and looking back at my PR, I am actually no longer sure it would solve this problem. I'll close the PR.

The only solution I currently see is to not look for sync on the prototype, but to call it based on the dependency passed in, similar to what the PR suggested.

Regarding using ajaxConfig on a BaseModel:
This does not work on the server, unless you create new classes for every request, because many requests come in and are being worked on asynchronously, and they all need different authentication tokens for API requests. If you have a base class, everyone would share the same tokens.
If you create a new class for every request you have a new problem: If some other module wants to import this class and extend it, it cannot easily do that. It needs to wait for the 'personalized' class to be available, then export the subclass based on that.

All of this is a lot of overhead, and continuation-local-storage, while being very elegant, kind of is a hack. The most solid and non-hacky, non-magicy way seems to be to just have a single component created per request that takes care of making all http calls for the models, and not allowing models to be instantiated just anywhere in the application, but only at the central sync manager.

from ampersand-model.

latentflip avatar latentflip commented on August 25, 2024

Regarding using ajaxConfig on a BaseModel:

Oh, sorry, I missed the point about being on the server.

Basically what's really in the way is Model.prototype.sync, which directly delegates to sync - and looking back at my PR, I am actually no longer sure it would solve this problem.

In that case can't you do something like:

var sync = require('ampersand-sync');
var AmpersandModel = require('ampersand-model');

var BaseModel = AmpersandModel.extend({
    sync: function (method, model, options) {
        //do whatever you need to
        //...
        // call original sync
        sync(/*args*/)
    }
});

Again, I'm sure I'm still not quite following you correctly, sorry! :)

from ampersand-model.

TimBeyer avatar TimBeyer commented on August 25, 2024

The thing is that I do not want a sync method on the model, I want to basically use ampersand-state only, in addition to the url method. And I want to reuse the fetch, save and destroy methods from ampersand-model, but instead of having them on the instances / their prototype, I want an external component that calls them like syncMethods.fetch.apply(state, arguments), because I really don't want developers to even think about being able to directly save, fetch or delete a model.

The way it currently works, I end up with some monstrosity like this:

var Promise = require('bluebird');
var Model = require('ampersand-model');

var sync = function (method, model, options) {
    // Imagine this actually does something
    return Promise.resolve();
};

module.exports = function dataManager(options) {

    var getSyncDelegator = function (sync, state) {
        var syncMethod = function () {
            return sync.apply(state, arguments);
        };

        var deleteSync = function () {
            delete state.sync;
            return state;
        };

        var syncable = {
            save: function (key, val, options) {
                state.sync = syncMethod;
                return Model.prototype.save.call(state, key, val, options).then(deleteSync);
            },
            fetch: function (options) {
                state.sync = syncMethod;
                return Model.prototype.fetch.call(state, options).then(deleteSync);
            },
            destroy: function (options) {
                state.sync = syncMethod;
                return Model.prototype.destroy.call(state, options).then(deleteSync);
            }
        };

        return syncable;
    };

    return {
        save: function (state, key, val, options) {
            var syncable = getSyncDelegator(sync, state);
            return syncable.save(key, val, options);
        },
        fetch: function (state, options) {
            var syncable = getSyncDelegator(sync, state);
            return syncable.fetch(options);
        },
        destroy: function (state, options) {
            var syncable = getSyncDelegator(sync, state);
            return syncable.destroy(options);
        }
    };
};

Not relying on Model.prototype.sync would turn this code into just this:

var Promise = require('bluebird');
var syncMethodsFactory = require('ampersand-sync-methods');

var sync = function (method, model, options) {
    // Imagine this actually does something
    return Promise.resolve();
};

module.exports = function dataManager(options) {

    var syncMethods = syncMethodsFactory(sync);

    return {
        save: function (state, key, val, options) {
            return syncMethods.save.call(state, key, val, options);
        },
        fetch: function (state, options) {
            return syncMethods.fetch.call(state, options);
        },
        destroy: function (state, options) {
            return syncMethods.destroy.call(state, options);
        }
    }
}

from ampersand-model.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.