Search code examples
javascriptnode.jsampersandampersand.js

How do I get the current folder in NodeJS for a Browserify'd file that relies on a base file in another folder?


I'm using AmpersandJS and I'm trying to emulate the pod structure of Ember so that, instead of the typical folders-per-type structure:

app
|-- views
    |-- index.js
    |-- login.js
    |-- people.js
|-- templates
    |-- index.jade
    |-- login.jade
    |-- people.jade

you have folders-per-component instead:

app
|-- index
    |-- view.js
    |-- template.jade
|-- login
    |-- view.js
    |-- template.jade
|-- people
    |-- view.js
    |-- template.jade
|-- base-view.js

I'm using templatizer to compile my templates:

templatizer(__dirname + '/app', __dirname + '/app/templates.js');

Which will make the template object look something like this (simplified for sake of explanation):

{
    "index.template": "<div>index</div>",
    "login.template": "<div>login</div>",
    "people.template": "<div>people</div>"
}

In the base view, I have the following, which will return the template by convention:

var BaseView = AmpersandView.extend({
  template: function() {
    // pretend that I'm cleaning up __dirname here
    return templates[__dirname].template;
  }
});

and in my other views, I'm extending the base view:

// in app/index/view.js:
var IndexView = BaseView.extend({ ... });

The problem I'm running into is that, when the base view goes through Browserify, __dirname is set to the folder of the base view template, and not the view that's extending it. As a result, __dirname will always be /app, even though /app/index/view.js is the view that's being rendered.

I was wondering if it's possible to get the dirname of the current view rather than the base view. I know that I can add something like templatePath to each view that the base view will read, but I'm trying to avoid having to do that.


Solution

  • So I think this comes down to a javascript scope issue. You'll need to grab __dirname from each subclass view's scope and tack it onto the instance for the override to work properly. There are several ways to achieve this (and I'm not familiar with Ampersand state extend), but my first suggestion would be:

    var IndexView = BaseView.extend({props: {__dirname: __dirname}});
    

    That will grab __dirname at the correct scope and make it available. Then you need to implement your BaseView template function referencing this.__dirname instead of just __dirname.

    var BaseView = AmpersandView.extend({
      template: function() {
        // pretend that I'm cleaning up __dirname here
        return templates[this.__dirname].template;
      }
    });