Meteor global variable not loading correctly - meteor

So I'm trying to create a global variable that copies the MongoDB database into a new array, so I keep server calls at a minimum.
It looks like this:
db = _.map(MyCollection.find().fetch()[0], function(item){return item});
I place this into my /lib/constants.js folder to make sure it loads before anything else in client. I place it inside client, it works.
Ultimately, the db as a global variable doesn't work. Not sure what I'm doing wrong. Also, if you would be kind to answer this question also: Can I do regular JS statements like loops inside the lib folder to make the result load before the client does?
Thanks!

Related

Meteor.JS: Subscribe no working

Im trying to subscribe my client side to my userFriends collection and Chrome's console display: userFriends is not defined
This is my code:
Server side...
userFriends = new Mongo.Collection("friends");
console.log(userFriends.find().fetch())
Meteor.publish("friends", function () {
return userFriends.find();
});
NOTE: The console.log display in the terminal an empty array which is good
Client side...
Meteor.subscribe("friends");
console.log(userFriends.find().fetch())
NOTE: This is where Chrome's console display the error
what am I doing wrong ?
Thank you
UPDATE 1: Now I can see the Friends collection in Chrome's console, but i cant insert data. I have the subscribe in client.js inside my client folder and my insert code is in friend.js inside client folder aswell.
The collection needs to be defined on both the client and the server. Typically this is done by placing the definition in a shared directory like lib:
lib/collections/user-friends.js
userFriends = new Mongo.Collection('friends');
Note the convention is to name the collection with the capitalized camel case version of the collection name. So calling it Friends would be more typical.
You need to declare the collection on both environments using shared code.
lib/user-friends.js
userFriends = new Mongo.Collection("friends");
client/user-friends.js
Meteor.subscribe("friends", function(){
console.log(userFriends.find().fetch());
});
In the client, be aware that collection subscriptions are asynchronous by nature (there's network latency on the client, inherent to fetching the documents from the server).
This is why if you console.log your collection content right after Meteor.subscribeing you'll get [], but if you wait until the subscription is ready using a callback, documents will be displayed correctly.
You have two correct answers but they do assume some knowledge for you. Here's what it looks like using Meteor's file structure (available at http://docs.meteor.com/#/full/structuringyourapp).
In your /lib (shared) directory
Make a file called "collections.js" and in it create your collection.
userFriends = new Mongo.Collection("friends");
I would instead do userFriends = new Mongo.Collection("userfriends"); so that your are always using the same word for your collection and you change the capitalization depending on if you're working on client or server. This is very helpful.
In Your /client directory
Make a file called "subscriptions.js" and in it subscribe to your collection.
Meteor.subscribe('friends');
In Your /server directory
Make a file called "publications.js" and in it publish your collection.
Meteor.publish('friends',function(){
return userFriends.find();
});
You don't need a fetch or anything there.
Essentially your code is failing because of where you're trying to house everything. What I've given you is three points of where you work. Client, Shared, Server. Set your app up that way and it will be easy to immediately figure out where you're working.
Hope that helps.

In Meteor, how to find which session variable triggers a template rerun

This is a general question about designing meteor applications or debugging meteor applications.
When I write meteor applications, I usually update session variable values to trigger re-runing a template helper function and/or re-rendering a template. So my application has quite a few different session variables.
Sometimes I find that the helper function gets re-run multiple times, but I can't think of any reason why it re-runs so many times. It must be some session variable gets updated and causes the re-run. Is there a way to figure out which session variable causes it?
The general question is: in a reactive design, when I see a template gets re-rendered, how to find why it gets re-rendered?
You could use Deps.autorun to quickly figure out which it is, If you're looking to debug its a quick a gritty way to do
Drop in the code like
Deps.autorun(function() {
Session.get("something");
console.log("Session something has changed");
});
Deps.autorun(function() {
Meteor.user()
console.log("Meteor user has changed");
});
You can place blocks of code like this on your client side to see which is changing. Each one will run once, initially, then after for each time the reactive variable inside it changes.
You would have to do this for each variable you use in your template and it would help you find out which is changing, each Deps.autorun block will run independently only when the variable inside it changes.

Angular-like client side data binding and reactivity with Meteor?

I'm trying to wrap my head around Meteor's way of dealing with reactivity and I want to make sure I've got some concepts right.
Take the follow reactivity example:
A user types something into a form field. The thing that he is typing is instantly displayed somewhere else on the page, as the user is typing, letter by letter. An instantaneous duplication.
From what I know about Angular, this is a very common example of reactivity. Angular binds the input directly to the output on the client side. There's nothing in between.
Correct me since I could be wrong, but Meteor can do this, but the input would first need to be captured and stored into a Mongo + MiniMongo DB (perhaps only as a collection in local storage), there would need to be a subscribe step, and those values would then be read and displayed on the page.
Is there a way to directly bind an event on the front end to another thing on the front end like Angular does?
Is this right? For Meteor to have the front-end-only reactivity of Angular it must first go through the intermediary of a collection, meaning extra code would be necessary to accomplish this compared to Angular?
The example in the Meteor Docs:
Deps.autorun(function () {
Meteor.subscribe("messages", Session.get("currentRoomId"));
});
So here, when the data of currentRoomId changes, the function is reactive to that data change and the function runs (in this case Meteor subscribes to messages).
Using Session variables is the only way I see of possibly binding two parts of a view together directly. Are there other ways?
Meteor's client-side reactivity system (Deps) is not coupled with its live MongoDB syncing. You can use it with any reactive data source which implements the right interface, including data sources which are entirely client-side. For example, you can use the built-in Session object. This is just a client-side key-value store with support for Meteor's reactivity, and you don't have to do any publish or subscribe to use it.
This standard way to do this sort of thing looks something like this:
<input id="field" value="{{fieldValue}}">
Template.form.fieldValue = function () {
return Session.get("fieldValue");
};
Template.form.events({
"input #field": function (evt) {
Session.set("fieldValue", $(evt.currentTarget).val());
}
});
Now the Session variable fieldValue is synced up to the form field. You can call Session.get("fieldValue") in some helper and that template will re-render when the user types in the form field. And if you call Session.set("fieldValue", "blah") then the form field will update itself.
As for your edit: You can make your own reactive data sources using Deps.Dependency, or you could meteor add reactive-dict although that's not documented. There may be packages on Atmosphere.

Update document in Meteor mini-mongo without updating server collections

In Meteor, I got a collection that the client subscribes to. In some cases, instead of publishing the documents that exists in the collection on the server, I want to send down some bogus data. Now that's fine using the this.added function in the publish.
My problem is that I want to treat the bogus doc as if it were a real document, specifically this gets troublesome when I want to update it. For the real docs I run a RealDocs.update but when doing that on the bogus doc it fails since there is no representation of it on the server (and I'd like to keep it that way).
A collection API that allowed me to pass something like local = true this would be fantastic but I have no idea how difficult that would be to implement and I'm not to fond of modifying the core code.
Right now I'm stuck at either creating a BogusDocs = new Meteor.Collection(null) but that makes populating the Collection more difficult since I have to either hard code fixtures in the client code or use a method to get the data from the server and I have to make sure I call BogusDocs.update instead of RealDocs.update as soon as I'm dealing with bogus data.
Maybe I could actually insert the data on the server and make sure it's removed later, but the data really has nothing to do with the server side collection so I'd rather avoid that.
Any thoughts on how to approach this problem?
After some further investigation (the evented mind site) it turns out that one can modify the local collection without making calls to the server. This is done by running the same methods as you usually would, but on MyCollection._collection instead of just on Collection. MyCollection.update() would thus become MyCollection._collection.update(). So, using a simple wrapper one can pass in the usual arguments to a update call to update the collection as usual (which will try to call the server which in turn will trigger your allow/deny rules) or we can add 'local' as the last argument to only perform the update in the client collection. Something like this should do it.
DocsUpdateWrapper = function() {
var lastIndex = arguments.length -1;
if (arguments[lastIndex] === 'local') {
Docs._collection.update(arguments.slice(0, lastIndex);
} else {
Docs.update(arguments)
}
}
(This could of course be extended to a DocsWrapper that allows for insertion and removals too.)(Didnt try this function yet but it should serve well as an example.)
The biggest benefit of this is imo that we can use the exact same calls to retrieve documents from the local collection, regardless of if they are local or living on the server too. By adding a simple boolean to the doc we can keep track of which documents are only local and which are not (An improved DocsWrapper could check for that bool so we could even omit passing the 'local' argument.) so we know how to update them.
There are some people working on local storage in the browser
https://github.com/awwx/meteor-browser-store
You might be able to adapt some of their ideas to provide "fake" documents.
I would use the transform feature on the collection to make an object that knows what to do with itself (on client). Give it the corruct update method (real/bogus), then call .update rather than a general one.
You can put the code from this.added into the transform process.
You can also set up a local minimongo collection. Insert on callback
#FoundAgents = new Meteor.Collection(null, Agent.transformData )
FoundAgents.remove({})
Meteor.call 'Get_agentsCloseToOffer', me, ping, (err, data) ->
if err
console.log JSON.stringify err,null,2
else
_.each data, (item) ->
FoundAgents.insert item
Maybe this interesting for you as well, I created two examples with native Meteor Local Collections at meteorpad. The first pad shows an example with plain reactive recordset: Sample_Publish_to_Local-Collection. The second will use the collection .observe method to listen to data: Collection.observe().

How to use Zend\Config (application wide variables)

Main question is self explanatory, but I'll give some side examples:
I'm having trouble figuring out databases, though it seems I can work out config with ServiceManager stuff
I want to use constants for cookie names, so I can change them easily if there are collisions. Current, I'm calling $config = new \Zend\Config\Config(include $_SERVER['DOCUMENT_ROOT'] . '/../config.php'); every time I want access to my global config.php file. A lot of previous solutions were in Zend 1 (eg Zend_Registry). Is this the right way to do it? It seems a little unwieldy using that over and over.
Is there a way to utilize a Module's configuration file to set module-wide-variables/constants?
Unless I'm completely missing it, there's no application.ini in Zend 2
Storing recaptcha public/private keys
I'm also using my config file for session-variables (same idea as $_SESSION[CONST_NAME]), which makes it really clumsy with the config file above. Is it better to hardcode the session names? Like:
$container = new Zend\Session\Container('auth');
$container->offsetSet('user', $user);
... // instead of
$container = new Zend\Zession\Container($config['auth']['containername']);
$container->offsetSet($config['auth']['user'], $user);
All configuration from each module.config.php or Module.php are put together into a big pot. You can easily access those via $this->getServiceLocator()->get('config')
When it comes down to constants, they should be placed inside the respective classes. Like
class UserStorage {
const SESSIONCONTAINERNAME = 'blubbusersession';
}
That way you can call \My\User\Model\UserStorage::SESSIONCONTAINERNAME whenever you need this info
As far as your example is concerned thought, there should be almost no need to var-code your session-container-name because the information from your modules session-data should be made available via your modules Service-Classes. But if you still need it, see aboves example.
Furthermore i think it may be a good idea for you to check out how zf-commons\ZfcUser does things

Resources