0

I'm trying to inject a gateway by using a node module. Not sure if I can do this because I get a 'object is not a function error' on the line var response = new controller(gateway).find();

or maybe I should be able to do this with a node moduile, but not doing this right.??

Note: Although the code in the controller is not using the gateway yet, I want to be able to inject it for now just to make sure I can.

someFile.js

var controller = require('someController');
var gateway = require('someGateway);

var response = new controller(gateway).find();

someGateway.js

'use strict';

module.exports = function(){
    var _data;

    return {
        data: function(someData){
            _data = someData;
        },
        find: function(){
            return _data;
        }
    };
}();

someController.js

'use strict';

module.exports = function(gateway){

    var _gateway = gateway;

    return {
        find: function(searchText){

            var response = {};

            if(typeof searchText === "undefined"){
                response.statusCode = 400;
            }

            return response;
        }
    };
}();

UPDATED:

I tried changing it to this:

someFile.js

var controller = require('someController');

var response = controller.find();

someControllerjs

'use strict';

var Controller = function(){

    var _find = function(searchText){
        var response = {};

        if(typeof searchText === "undefined"){
            response.statusCode = 400;
        }

        return response;
    };

    return {
        find: _find
    };

}();

module.exports = Controller;

I'm trying to go with the pattern this dude has but still I get the same error. http://rob.conery.io/2012/02/25/testing-your-model-with-mocha-mongo-and-nodejs/

PositiveGuy
  • 17,621
  • 26
  • 79
  • 138
  • YES NO MORE FOLLOWING ROB CONERY. That dude has had bad posts in the past. Remember his very old REST in ASP.NET MVC where he suggested having verbs in the urls. – PositiveGuy Jul 27 '15 at 04:32

1 Answers1

0

I'm not 100% sure what it is exactly you're trying to achieve with this code, but maybe I can shed some light on what is going on :)

  1. var gateway = require('someController');

You ask Node.js to load some module called 'someController'. It goes and finds someController.js and begins executing the file.

  1. module.exports = function(gateway){ ... }();

This function is immediately invoked (being a IIFE) and whatever is returned from it is assigned to be the "output" of that module. In your function, you return a plain object with a find method.

In memory, controller now equals this object:

{
    find: function(searchText){

        var response = {};

        if(typeof searchText === "undefined"){
            response.statusCode = 400;
        }

        return response;
    }
};
  1. var response = new controller(gateway).find();

You call new on the object above, and try to call it as a function. However, it is an object. You can't call controller(gateway) because controller is only equal to an object. Therefore, you get the error that you mentioned.


I think you may accidentally be trying to assign a function to module.exports, rather than an IIFE. Keep in mind that the brackets at the end of each of your modules (}();) is causing the function to execute immediately and set the result value to be the value of the module. Try removing the function call brackets at the end of your module and you should have better luck!

Community
  • 1
  • 1
Chris Foster
  • 2,639
  • 2
  • 23
  • 30
  • my intent is that I need to be able to inject the gateway into the constructor of the controller. – PositiveGuy Jul 27 '15 at 03:30
  • fyi I'm trying to use this pattern http://rob.conery.io/2012/02/25/testing-your-model-with-mocha-mongo-and-nodejs/ – PositiveGuy Jul 27 '15 at 03:45
  • I even tried just doing this: var response = controller.find(); but still get 'undefined is not a function' – PositiveGuy Jul 27 '15 at 03:48
  • @WeDoTDD You misunderstood what I said, and removed the wrong brackets. I meant you should remove the brackets at the end of `someController` and `someGateway` to make this code functional. – Chris Foster Jul 27 '15 at 03:58
  • @WeDoTDD If you wanted to keep his design pattern of using an IIFE (keeping the brackets at the end), then you can't treat `gateway` and `controller` as functions, because they aren't functions. They're objects, you can't call them. – Chris Foster Jul 27 '15 at 03:58
  • @WeDoTDD However, I would highly recommend against following that blog post and instead I'd recommend going with a more traditional module setup. The person who wrote that blog post misunderstands how scoping works in Node.js modules and is doing that abstract-pattern-setup unnecessarily. – Chris Foster Jul 27 '15 at 03:59
  • can you explain what I should be doing then...what do you mean more traditional – PositiveGuy Jul 27 '15 at 04:02
  • it works fine with the brackets in if I just don't pass the gateway to the controller but anyway yea I'm trying to find a better way to encapsulate and expose stuff through exports while still being able to declare private variables in my module and expose certain properties publicly as well as be able to inject fakes into my controller – PositiveGuy Jul 27 '15 at 04:05
  • 1
    @WeDoTDD The author mislead you regarding how Node.js modules work. Each module has its own namespace. You can declare whatever variables you want in the file namespace and it won't leak into other modules. **Only** `module.exports` is exported out of the file. You can just set it to be your model – Chris Foster Jul 27 '15 at 04:08
  • @WeDoTDD This discussion has gone out of scope of the original question. If you'd like to continue chatting, please move this discussion to chat and I'm happy to answer questions. Please remember to accept the answer if you feel it answered your original question. – Chris Foster Jul 27 '15 at 04:09
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/84335/discussion-between-we-do-tdd-and-chris-foster). – PositiveGuy Jul 27 '15 at 04:10