Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Global classes with Meteor >0.6.0 and CoffeeScript

Since the release of Meteor 0.6.0 and the addition of file-level JavaScript variable scoping, I'm facing an issue using CoffeeScript classes, each of them being defined in its own respective file.

foo.coffee:

class Foo
  ...

subfoo.coffee:

class Subfoo extends Foo
  ...

As expected, and because of the changes introduced in Meteor 0.6.0, I'm getting the following error:

ReferenceError: Foo is not defined

Here's my question: how should one handle class definitions across files with CoffeeScript and Meteor >0.6.0? Ideally: is there a convenient way not to modify too much the way classes are defined in order to make sure these definitions (and core parts of my application) are not Meteor-dependent?

like image 939
jbmusso Avatar asked Apr 05 '13 10:04

jbmusso


2 Answers

As noted in the CoffeeScript section of the docs:

Global variables can be set in CoffeeScript by using this (or CoffeeScript's @ shorthand)

As it turns out, CoffeeScript classes can be defined like:

class @Foo

which compiles to:

this.Foo = (function() {
  function Foo() {}
  return Foo;
})();

Assuming that foo.coffee is loaded before subfoo.coffee you can then do:

class @Subfoo extends Foo

Assuming, of course, that Subfoo needs be be assigned to the global scope. It's also worth mentioning that you'll need to expose your collections in a similar way. For example:

@Players = new Meteor.Collection 'players'
like image 159
David Weldon Avatar answered Oct 05 '22 18:10

David Weldon


Also note that classes such as "Foo" are themselves a value, that you can assign to variables or put into a namespace yourself.

Using class @Foo is a great shortcut when you want to put that value directly into the global namespace.

But if you want to, you can also leave variables local and then add them to the global namespace yourself:

class Foo
  ...

Players = new Meteor.Collection 'players'

doThat = -> ...

_.extend(this, {Foo, Players, doThat})

Or if you'd prefer, you can have your "foo" module define just one global object foo that contains the exported values:

@foo = {Foo, Players, doThat}

Now modules that use the "foo" module can reference the values through the global variable foo:

class Subfoo extends foo.Foo
  ...

Or, if you'd rather be able to type just Foo even when exporting only foo, you can unwrap foo at the top:

{Foo, Players, doThat} = foo

class Subfoo extends Foo
  ...
like image 33
Andrew Wilcox Avatar answered Oct 05 '22 18:10

Andrew Wilcox