Use RequireJS.
In one file called "my-classes.coffee", define the namespace.
define [], ->
# You need this if you want it to work in multiple environments.
# Otherwise just use `window` to work in the browser.
root = exports ? this
root.MyClasses = {}
You can define your class in another file called "aa.coffee".
define ['my-classes'], (MyClasses) ->
class MyClasses.Aa
@someProp: true
Another file:
define ['my-classes'], (MyClasses) ->
class MyClasses.Bb
@someProp2: false
Now when you require, it should export MyClasses
which includes MyClasses.Aa
.
require ['my-classes', 'aa'], (MyClasses, _) ->
console.log MyClasses.Aa.someProp
One issue with doing it this way is that you can't depend on just "my-classes" in the require
statement. If you did that, MyClasses.Aa
would be undefined. But you can't depend on just "aa" either, because "aa" doesn't export anything except by adding to MyClasses. In the above code snippet, MyClasses.Bb
is undefined because I haven't explicitly depended on it. This is why many people either use one giant file or duplicate the boilerplate of re-exporting the namespace.
If anyone knows how to fix this, please let me know.
I, personally, find RequireJS to be complicated to use, and there are many different ways to set it up. One way I've used it with jasmine is by using a cake task to precompile my CoffeeScript down to JavaScript, and then have spec files like this.
requirejs = require('requirejs')
# Set the baseURL to your compiled JS dir.
requirejs.config { baseUrl: __dirname + '/../lib' }
requirejs ['my-classes', 'aa'], (MyClasses, _) ->
describe "someProp", ->
it "should be true", ->
expect(MyClasses.Aa.someProp).toEqual true
This may not be the best way, but I was able to use it to run modules in the browser, on a Node server, and in jasmine-node tests. I've also seen some people use custom runners to avoid the boilerplate in their spec files.
If you'd rather not use RequireJS, you may find this question helpful. It works by using the namespace
function defined on the CoffeeScript FAQs.