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

Simulate resulting doc on before.update hooks #91

Open
gwendall opened this issue Feb 11, 2015 · 15 comments
Open

Simulate resulting doc on before.update hooks #91

gwendall opened this issue Feb 11, 2015 · 15 comments

Comments

@gwendall
Copy link

It would be handy to be able to simulate (using the initial doc + the modifier) what the doc after update would look like. It would make things like security checks pretty easy - right now we have to check $set, $addToSet, etc attributes manually to control what fields are about to get updated. Is there anything on the roadmap for that?
If not that would not be too hard, just patching what was done on minimongo. (https://github.com/meteor/meteor/blob/07b6a2245a1e091830844881e7376c38adda3592/packages/minimongo/modify.js)

@mizzao
Copy link
Contributor

mizzao commented Feb 11, 2015

Might help consolidate the logic for this if hooks were integrated into core (#92 and meteor/meteor#395).

@bensmeets
Copy link

I'm running into this one right now, I (try to) use the before.update hook to calculate some computed fields on the doc. But since there are quite some dependencies on the calculation on different fields in either the doc or the modifier (depending on which one is set and which one will be overridden by the modifier) it's a bit of a headache.

Did someone manage to find a smarter solution than what I'm currently thinking of which is a whole bunch of "if this then that or else use modifier if set" kind of code?

@gwendall
Copy link
Author

@bensmeets Thinking about it now, you could do that through a dummy collection, ie:

TempCollection = new Mongo.Collection("temp");
var simulateDoc = function(doc, modifier) {
  TempCollection.insert(doc);
  var selector = { _id: doc._id };
  TempCollection.update(selector, modifier);
  var simulation = TempCollection.findOne(selector);
  TempCollection.remove(selector);
  return simulation;
}

@matb33
Copy link
Collaborator

matb33 commented Mar 23, 2015

I agree it would be helpful. Have any of you tried just leveraging LocalCollection._modify directly? Something like:

coll.before.update(function (userId, doc, fieldNames, modifier, options) {
  LocalCollection._modify(doc, modifier);
  // doc should be simulated (I think)... do some logic
});

It would be good to try this in the wild for a bit to get a feel for it.

@bensmeets
Copy link

@gwendall Quite the creative solution 👍

@matb33 Tried but I can't seem to find how to call _modify. Both through LocalCollection._modify as through MyCollectionName._modify I get an method undefined error. Do you happen to know how to call it?

@bensmeets
Copy link

I've got "some" sort of access to "_modify" in the client through

Package.minimongo.LocalCollection._modify

Callable, but it returns undefined in the server. Checked, the function does exist on the server, but for now still returns undefined.

@matb33
Copy link
Collaborator

matb33 commented Mar 23, 2015

What you need to do is find a way to use minimongo on the server. I'll be honest... I don't remember how to do this without packages. My meteor projects are all made up entirely of packages, no client or server etc folders... so for me it's easy, I just api.use("minimongo", ["server", "client"]); from whichever of my app packages would need access to LocalCollection.

Whatever the equivalent would be for non-all-package projects, that's what you're looking for.

@bensmeets
Copy link

I couldn't get it exactly right, but I'm using a variation of @gwendall 's code. Like this:

simulateDocumentModifier: function (doc, modifier) {
    var c = new Package.minimongo.LocalCollection('simulations');
    c.insert(doc);

    var sel = {
      _id: doc._id
    };

    c.update(sel, modifier);

    var sim = c.findOne(sel);
    c.remove(sel);

    return sim;
  }

But the effect is a bit opaque. Just hoping I'm not creating a lot of overhead or database collections with it. It works though :)

@matb33
Copy link
Collaborator

matb33 commented Apr 22, 2015

If using LocalCollection._modify(doc, modifier); as I mentioned actually does work, perhaps I could have the collection-hooks package use the minimongo package on both server and client, and offer a CollectionHooks.modify or something like that which just wraps LocalCollection._modify(doc, modifier);

I'm hoping someone can confirm that using LocalCollection._modify(doc, modifier); does what we would need it to do.

@trusktr
Copy link

trusktr commented Mar 7, 2016

Yep, depending on minimongo (serverside included) and using LocalCollection._modify works great. It's not publicly documented Meteor API, so took a while for me to find it. You might not even need to wrap it. In the before.update and before.upsert hooks, maybe you can just have oldDoc and newDoc parameters? But, documenting the use of modify function would also work.

@pdiniz13
Copy link

Worked for me as well, as long as the minimongo dependency is there for both client and server, this solution works very well.

@chneau
Copy link

chneau commented May 20, 2016

Hello, LocalCollection._modify works super fine for me !

I think it could be a good thing if " LocalCollection._modify " was on the README as a tip to get the result doc in updates.

nicooprat added a commit to nicooprat/meteor-collection-counter that referenced this issue Jun 2, 2016
Instead of calculating all possible operations, create a temporary local document using Minimongo, apply the modifier, and get the modified document. Too bad I didn't find this a few days earlier...

Meteor-Community-Packages/meteor-collection-hooks#91
@zimme
Copy link
Member

zimme commented Feb 12, 2017

I'll look into wrapping LocalCollection._modify and attaching it to this inside the hooks.

@davidsavoie1
Copy link

Hi there!

Has there been any development or "official" support for this now? It would indeed be way easier to fire the proper hooks if we could diff between current and to-be-updated document. I'm just starting to integrate collection hooks in my app, and this is the most difficult thing for me so far.

Is the proposed LocalCollection._modify still relevant and working (since this thread dates a little...)?

Thanks all for the nice library though.

@luixal
Copy link

luixal commented Nov 22, 2018

This is still needed, any news? :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants