Meteor: How to know which template helper is throwing an exception - meteor

After having changed the semantics of a Session variable used in lots of places in the code, I am left with a regression where I get the "Exception in template helper" error at page load.
So I screwed up, and there is somewhere where I am using that variable where I have not modified the code to handle the new semantics. But I can't find where....
The traceback gives me no clue, as it has only entries from the meteor javascript files, no informtion about my application files:
Exception in template helper: Error: $in needs an array
at Error (native)
at Object.ELEMENT_OPERATORS.$in.compileElementSelector (http://jesper-lab:3000/packages/minimongo.js?e8806aa7782b729b2517ebc0cd10b321667f1427:1887:15)
at http://jesper-lab:3000/packages/minimongo.js?e8806aa7782b729b2517ebc0cd10b321667f1427:1569:19
at Function._.each._.forEach (http://jesper-lab:3000/packages/underscore.js?0a80a8623e1b40b5df5a05582f288ddd586eaa18:164:22)
at operatorBranchedMatcher (http://jesper-lab:3000/packages/minimongo.js?e8806aa7782b729b2517ebc0cd10b321667f1427:1549:5)
at compileValueSelector (http://jesper-lab:3000/packages/minimongo.js?e8806aa7782b729b2517ebc0cd10b321667f1427:1453:12)
at http://jesper-lab:3000/packages/minimongo.js?e8806aa7782b729b2517ebc0cd10b321667f1427:1432:9
at Function._.each._.forEach (http://jesper-lab:3000/packages/underscore.js?0a80a8623e1b40b5df5a05582f288ddd586eaa18:164:22)
at compileDocumentSelector (http://jesper-lab:3000/packages/minimongo.js?e8806aa7782b729b2517ebc0cd10b321667f1427:1415:5)
at _.extend._compileSelector (http://jesper-lab:3000/packages/minimongo.js?e8806aa7782b729b2517ebc0cd10b321667f1427:1392:12)
Is there any way I can find out WHICH template helper is throwing this exception? (Besides putting breakpoints in all of them (hundreds...))

I'm not sure it's the best possible way but what I do is use a generic try_catch function:
#try_catch = (f) ->
return (args) ->
try
f(args)
catch e
console.log e
and wrap it around every template helper I want to debug.

Related

What the proper way to avoid console warning, when meteor collection is not ready

Every time I refresh the page I receive the following console warning for every single helper that is returning something to template from collection. I know the reason is because the subscription is not ready yet, but what is the solution?
Exception in template helper: TypeError: Cannot read property 'x' of undefined.
I'm already using if(collection.find({}) !== undefined) , but this makes my codes so messy, there must be a way to fix this issue. then I tried guards and still not 100% solved.
In addition to Brendan's answer, using Blaze you can check if the subscriptions for the template is ready using
this.subscriptionsReady()
Which checks all the subscriptions scoped to the template with
this.subscribe()
in your onCreated or onRendered blocks
Meteor.subscribe returns a handle with a reactive method called .ready(). You can use that in your helper to only return the mongo cursor once it's ready.
Edit: docs

How can I make a function in one module accessible to another module?

In my custom module, I would like to call uc_quote_request_quotes() (for testing purposes). The module has obviously not been loaded yet because when I try to call it, I get an error:
Fatal error: Call to undefined function uc_quote_request_quotes()...
tf_common.module
function tf_common_test()
{
module_load_include('module', 'uc_quote');
uc_quote_request_quotes();
}
In uc_quotes.pages.inc I have the function defined
function uc_quote_request_quotes() {
//code
}
EDIT:
I had to change the module_load_include line to be module_load_include('inc', 'uc_quote', 'uc_quote.pages');
but that makes me question:
Is there a way to load the entire module or do I have to load each file individually like this?
I don't really want to change the info file to make the other module a dependency because this is only needed as a test function.
The reason uc_quote_request_quotes() isn't available to the tf_common module is because the uc_quote module is loaded after tf_common is. Look into changing the weight of the tf_common module to be loaded after or change uc_quote to be loaded before.

can you use tinytest to test a package that uses other packages

I have some tinytests, simple server unit tests.
Separately they run fine, but if i run them together I get errors on my collections.
What else might cause an error like the below?
I think its related to defining the exports in a JS file and the other classes in coffeescript and some scoping issue is complicating things. "Told you not to use coffeescript" i hear. But then again, it maybe something else!
os.osx.x86_64/dev_bundle/server-lib/node_modules/fibers/future.js:245
W20150418-17:39:20.312(-7)? (STDERR) throw(ex);
^
Error: A method named '/Profiles/insert' is already defined
at packages/ddp/livedata_server.js:1461:1
at Function._.each._.forEach (packages/underscore/underscore.js:113:1)
at [object Object]._.extend.methods (packages/ddp/livedata_server.js:1459:1)
at [object Object].Mongo.Collection._defineMutationMethods (packages/mongo/collection.js:90
at new Mongo.Collection (packages/mongo/collection.js:209:1)
at [object Object].Meteor.Collection (packages/dburles:collection-helpers/collection-helper
at __coffeescriptShare (packages/local-test:dcsan:mpgames/lib/exports.js:2:1)
at /private/var/folders/lw/6kdr1_9j3q1ggldr_c798qy80000gn/T/meteor-test-run126tw73/.meteor/
FWIW the app has no problems running, its just the tests that fail.
This error means you defined the Profiles collection more than once. My strategy in dealing with this problem has been to:
Use a global definition via api.export for any collections which actually should be defined by a package (e.g. if the posts package defined a Posts collection).
Define all other collections needed by the test with a null collection name (unmanaged) and use a reset like the following before each test:
var resetCollection = function(name) {
var Collection = this[name];
if (Collection)
// if the collection is already defined, remove its documents
Collection.remove({});
else
// define a new unmanaged collection
this[name] = new Mongo.Collection(null);
};
So if you call resetCollection('Posts') it would only define a new collection if needed and ensure its documents were removed. This way, you'll avoid multiple definitions and you'll start with a clean DB each time.

Meteor: The Loop of Death

I have noticed something really embarrassing with Meteor. When an error occurs inside a method on the server, this makes the entire code of the method to be rerun. This can lead to some unexpected results and some kind of trouble. For instance:
Meteor.methods
'someMethod': ->
# we insert an element in the database
Collection.insert({ record: "We want this record to be inserted only once." })
# We just made a mistake here, let's say that the object is not defined.
variable = object.property
return variable
What happened in my case is that Meteor throws an error saying that it cannot read the property of undefined (I can see it within the server logs) and then rerun the code of the method repeatedly throwing the same error again. I can see a lot of records inserted on my database when it should have one.
I don't know if there is a way to ask meteor to not rerun the code when an error occurs or some kind of thinking I need to learn while developing an application with it.

How to handle errors loading with the Flex Sound class

I am seeing strange behaviour with the flash.media.Sound class in Flex 3.
var sound:Sound = new Sound();
try{
sound.load(new URLRequest("directory/file.mp3"))
} catch(e:IOError){
...
}
However this isn't helping. I'm getting a stream error, and it actually sees to be in the Sound constructor.
Error #2044: Unhandled IOErrorEvent:.
text=Error #2032: Stream Error. at... ]
I saw one example in the Flex docs where they add an event listener for IOErrorEvent, SURELY I don't have to do this, and can simply use try-catch? Can I set a null event listener?
IOError = target file cannot be found (or for some other reason cannot be read). Check your file's path.
Edit: I just realized this may not be your problem, you're just trying to catch the IO error? If so, you can do this:
var sound:Sound = new Sound();
sound.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
sound.load(new URLRequest("directory/file.mp3"));
function ioErrorHandler(event:IOErrorEvent):void {
trace("IO error occurred");
}
You will need to add a listener since the URLRequest is not instantaneous. It will be very fast if you're loading from disk, but you will still need the Event-listener.
There's a good example of how to set this up (Complete with IOErrorEvent handling) in the livedocs.
try...catch only applies for errors that are thrown when that function is called. Any kind of method that involves loading stuff from the network, disk, etc will be asynchronous, that is it doesn't execute right when you call it, but instead it happens sometime shortly after you call it. In that case you DO need the addEventListener in order to catch any errors or events or to know when it's finished loading.

Resources