Publish structured, reactive data for the customer (outside of the database collections)

I am looking for the most effective solution for sending structured data to a client in a Meteor structure upon request.

RELEASE: Sometimes, before sending data from a database to a client, you want to add some additional server-side information sent to the client (that is, security credentials for many objects). This data can be time critical (i.e. due to the expiration timestamp) and therefore should not be stored in db. Furthermore, this data sometimes cannot be processed on the client side (i.e. due to security reasons). In many cases, this data will be structurally related to the actual database data, but also very related to a single query, as you might want it to be dropped and regenerated on a new query.

YOU CAN (at least by design ..):

  • create a second collection, save and publish your data related to the request, and take the recording overhead, and then, i.e. in Meteor.myTemplate.destroyed=function(){...} , delete the data again taking other overhead.

    / li>
  • store each entry in a session variable, but then you should also take care of it to delete it later ( Meteor.myTemplate.destroyed=function(){...} ), now it is my favorite, but I am having problems storing large objects there .

  • store this data in dom (i.e. in attributes or data fields of hidden or visible elements)
  • generate this data from dom using Meteor.call('method',arguments,callback(){...}) , storing the corresponding arguments in dom and injecting them back using jQuery into callback(){...} .

YOU CAN'T: (by design!)

  • use transformations Meteor.publish("name",function(){...}) on the server
  • use Meteor.call() in the conversion to Template.variable=function(){return collection.find(...)} (also not if you have the corresponding Meteor.method() on the client to guess the result!).

Again, I am looking for the best solution for this.

+3
performance javascript meteor
source share
4 answers

Jim Mack created a good example that proves how well it works for storing db data, as well as additional conversion properties in the Session variable. Unfortunately, this example is not reactive and does not perform the desired “transformations” after re-rendering the Meteor magic. So I grabbed his cool code and added reactivity back, this is thin code that works very well, but will surpass Jim Max's example in terms of efficiency.

lolz.html

 <head> <title>lolz</title> </head> <body> {{>myItems}} </body> <template name="myItems"> <h3>Reactive Item List with additional properties</h3> <button id="add">add</button> <button id="remove">remove</button> <dl> {{#each items}} <dt>data: {{caption}}</dt> <dd>added property: {{anotherProp _id}}</dd> {{/each}} </dl> </template> 

lolz.js

 items = new Meteor.Collection('Items'); if (Meteor.isServer) { items.allow({ insert: function (userid, doc) { return true; }, remove: function(userid,doc){ return true; } }); while(items.find().count()>0){ items.remove(items.findOne()._id); } while (items.find().count() < 3) { items.insert({caption: 'LOLCATZ RULZ'}); } Meteor.publish('Items', function () { return items.find(); }); Meteor.methods({ 'getAdditionalProps': function() { additionalProps={}; items.find().forEach(function(doc){ additionalProps[doc._id]=reverse(doc.caption); }); return additionalProps; } }); function reverse(s){ // server side operation, ie for security reasons return s.split("").reverse().join(""); }; } if (Meteor.isClient){ Meteor.subscribe('Items'); Meteor.startup(function(){ getAdditionalProps(); itemsHandle=items.find().observe({ added : function(doc){ getAdditionalProps(); }, removed : function(doc){ getAdditionalProps(); }, changed : function(docA,docB){ getAdditionalProps(); } }); }); Template.myItems.rendered=function(){ console.log(new Date().getTime()); }; Template.myItems.items=function(){ return items.find(); } Template.myItems.anotherProp=function(id){ return Session.get('additionalProps')[id]; } Template.myItems.events({ 'click #add':function(e,t){ items.insert({caption: 'LOLCATZ REACTZ'}); }, 'click #remove':function(e,t){ items.remove(items.findOne()._id); } }); } function getAdditionalProps(){ setTimeout(function(){ Meteor.call('getAdditionalProps',function(error,props){ Session.set('additionalProps',props); }); },0); } 
0
source share

To solve the conversion problem that I care about because I think that from the point of view of smart models that do something and not a bunch of anonymous functions, here is an example of converting a server reaching a client (not reactive as it is, by call, not to publish, but to illustrate the discussed item of server transformations).

You will receive the following:

 each image local

 data: LOLCATZ RULZ
   transform:
 data: LOLCATZ RULZ
   transform:

 each image server transformed

 data: LOLCATZ RULZ
   transform: XYZ
 data: LOLCATZ RULZ
   transform: XYZ

from

 <template name='moritz'> <h3>each image local</h3> <dl> {{#each images}} <dt>data: {{caption}}</dt> <dd>transform: {{secretPassword}}</dd> {{/each}} </dl> <h3>each image server transformed</h3> <dl> {{#each transformed}} <dt>data: {{caption}}</dt> <dd>transform: {{secretPassword}}</dd> {{/each}} </dl> </template> if (Meteor.isServer) { Images = new Meteor.Collection('images', { transform: function (doc) { doc.secretPassword = 'XYZ' return doc } }); Images.allow({ insert: function (userid, doc) { return true; } }); if (Images.find().count() < 1) { Images.insert({ caption: 'LOLCATZ RULZ'}); } Meteor.publish('images', function () { return Images.find(); }) Meteor.methods({ 'transformed': function() { return Images.find().fetch(); } }) } else { Images = new Meteor.Collection('images'); imageSub = Meteor.subscribe('images'); Template.moritz.helpers({ 'images': function () { console.log(Images.find().count() + ' images') return Images.find(); }, 'transformed': function () { // Should be separated, call should be in route for example Meteor.call('transformed', function(err,data){ Session.set('transformed', data); }); return Session.get('transformed'); } }); } 
+2
source share

Take a look at Meteor Streams , you can send something directly to the client from the server without the need to use collections on the client.

You can do something with the received message (I use an example from the meteor shower site):

Client

 chatStream.on('message', function(message) { if(message.expiry > new Date()) { //Do something with the message (not being read from a collection) } }); 

Despite the fact that you do this with some intention not to store it, be careful that simple tools (Chrome Inspector) can reach their maximum on the Network / Websocket tab (even if it is encrypted via SSL) and see that the raw data is transmitted through.

While I'm not sure of your intentions, if it is for security in any scenario, you never trust the data that you receive from the client.

0
source share

Your first line would seem to ideally answer with “Mongo collections”, but then I read some conflicting ideas and conclusions, with which I am not sure I agree. (For example, why can't you do these two things? Because it should happen on the server?) The most confusing expression for me is:

This data can be time critical (i.e. due to the expiration timestamp) and therefore should not be stored in db.

I don’t understand what kind of assumptions are included in this conclusion, but if you think that the data in dom should be plausible, then for points 2 and 3 above you would seem to be open to systems that are much less efficient than mongo db .

You know that from the server you can publish the second collection of additional server-generated calculations that you generate on the fly from the data, and place them with the data once on the client. As a parent-child relationship: when displaying a client document, pull additional data from the server from the dynamic collection and process it in your templates.

0
source share

All Articles