Using latest VSCode version 1.30.2 and it doesn't see the functions that are inside the exported module.
this is in model.js
var userModel = mongoose.model('userModel', usersSchema);
userModel.isUsernameTaken = isUsernameTaken;
module.exports = userModel;
function isUsernameTaken(username) {
return userModel.findOne({username:username});
}
and in app.js
var userModel = require('./model');
Now upon typing userModel. in app.js I should see a suggestion for autocompletion of isUsernameTaken, but it's not there and also not any of the functions declared in model are "visible". However if I type the exact function name (case-sensitive). (ex: userModel.isUserNameTaken(etc)) it works. What is wrong ?
I managed to fix it by changing in model.js
module.exports.default = userModel;
and then in another file:
var userModel = require(./model).default;
Now intellisense works as it should.
When you say userModel.isUsernameTaken(username), what you are really saying is mongoose.model('userModel', usersSchema).isUsernameTaken(username), in which this would return as undefined. What you would have to do is make user Model into an object with the mongoose.model('userModel', usersSchema) inside of it. Kind of like this:
var userModel = function () {
this.model: mongoose.model('userModel', usersSchema),
this.isUsernameTaken: (username) => {
return this.model.findOne({username:username});
}
};
Then if you wanted to access these attributes you could use
var user = new userModel(); then use user.isUsernameTaken(/*put username here*/);. Or if you wanted to access the model alone you could do: user.model. I hope this answers your question.
Related
Anyone know why this is happening?
I have a pretty complex system so to simplify it we have this code:
profile_manager.js
const Profile = require('./profile');
class ProfileManager {
doThing() {
const prf = new Profile("Lemon", "ade");
}
}
const prfManager = new ProfileManager();
module.exports = prfManager;
profile.js
class Profile {
constructor(arg0, arg1) {
//do thing
}
}
module.exports = Profile;
index.js
const prfManager = require('./profile_manager');
prfManager.doThing();
Once .doThing() is called, I get a TypeError saying that "Profile is not a constructor".
HOWEVER... When I change profile_manager.js to the following code below, it works perfectly. No TypeError.
class ProfileManager {
doThing() {
const Profile = require('./profile');
const prf = new Profile("Lemon", "ade");
}
}
const prfManager = new ProfileManager();
module.exports = prfManager;
I even console.logged the prf object and it works the way I want it to. Why does it only work when I move the "const Profile = require('./profile');" within the method but when I put it at the top of the module, it does not want to work.
I found out that profile.js had an instance of profile_manager.js or something like that
This post talks more about it How to deal with cyclic dependencies in Node.js
Quoting only the important parts of the code.
This is my server.js in the node backend server
//routes
const userapi = require('./api/routes/user');
//models
require('./api/models/userModel');
//use routes
userapi(app);
on my userapi which is my routes I call my userController
(function () {
'use strict';
module.exports = function (app) {
var userCtrl = require('../controllers/userCtrl');
app.post('/api/validate_user', function(req, res, next){
userCtrl.validate_user(req, res);
});
}
})();
and this is my userController code. In the future, i will write a code that will handle all the transaction from my MongoDB.
'use strict';
var mongoose = require('mongoose'),
model = mongoose.model('users'),
brcpyt = require('bcrypt');
module.exports = function() {
return {
validate_user: function(req, res) {
console.log('here');
}
}
};
The problem is, everytime I make a http request from my frontend. I get an error that says userCtrl.validate_user is not a function. My frontend can access the endpoints of '/api/validate_user' and the var userCtrl = require('../controllers/userCtrl') is a correct file path, but everytime that I type userCtrl to my routes it does not give me function validate_user
You really don't need to be wrapping your modules in IIFEs. That said, the issue you are seeing specifically is because your userCtrl module is exporting a function that, when called, returns an object which will then have a validate_user member -- it's not exporting an object directly. Try checking the value of typeof userCtrl - it'll be function instead of an object, which is what you're expecting here :)
Specifically, the following should work with no changes to userCtrl:
var userCtrl = require('../controllers/userCtrl')()
Notice the extra parenthesis at the end? That will invoke the exported function and give you back an object with a validate_user method. This pattern is sometimes used when you'd like to pass some options to the module, like a factory pattern. For example,
const userCtrlFactory = require('../controllers/userCtrl')
const userCtrl = userCtrlFactory({ option: value })
This, however, is not the best way to do so, you would be using classes for that.
I recommend you drop the IIFEs from your code ((function () {})()) and just have a top-level module.exports (like you did with the userCtrl) that exports either an object or a class, depending on what you need from it. For userCtrl, just export an object directly as you're not passing options or have a need for "instantiating" a controller more than once:
'use strict';
module.exports = {
validate_user: ...
};
require gives you the value assigned to module.exports, so your code is like:
var userCtrl = function() {
return {
validate_user: function(req, res) {
console.log('here');
}
}
};
userCtrl.validate_user(...);
Do you see the bug now? userCtrl is a function, and therefore doesn't have a validate_user property ...
I am working up a proof of concept for the Segregated DOM pattern and am using Browserify as my asset pipeline. As a result I am "requiring" modules as I need them in the code. Please see this very simple code example:
var loginForm = require('page-objects/loginForm');
lf = loginForm();
lf.signInButton.on('click', function(event){
event.preventDefault();
lf.email.val('TEST')
})
and here is the page object:
module.exports = LoginForm;
function LoginForm(){
var $ = require('jQuery'),
navbarForm = $('form.navbar-form');
return {
email: navbarForm.find('input[placeholder="Email"]'),
password: navbarForm.find('input[placeholder="Password"]'),
signInButton: navbarForm.find(':button')
}
}
I do not understand and cannot find a search that returns an answer as to why I need to instantiate the objects to use them. The examples I found on the Browserify GitHub and the Handbook do not show that as a requirement. However if I do not "new up" an object like this in my code the module is not found...I would like to know why that is. Are there changes I can make to my code to NOT have to do this?
Code without the object instantiation:
var loginForm = require('page-objects/loginForm');
loginForm.signInButton.on('click', function(event){
event.preventDefault();
loginForm .email.val('TEST')
})
At this moment, you export a function which returns an object. To retrieve the object, you have to execute the exported function first. If you just want the object without first executing a function, just export the object instead of a function:
var $ = require('jQuery'),
var navbarForm = $('form.navbar-form');
module.exports = {
email: navbarForm.find('input[placeholder="Email"]'),
password: navbarForm.find('input[placeholder="Password"]'),
signInButton: navbarForm.find(':button')
}
I'm writing a Protractor test and in my test.step.js file I have
element(by.css('...')).getText().then(function (text) {
expect(text).to.equal('expectedText');
});
This works as expected and passes.
Instead I created a test.page.js file and in there put this.field = element(by.css('...')); and then in my step file had
"use strict"
module.exports = function exampleTest() {
var TestPage = require("...");
var testPage = new TestPage;
...
test.Then(..., function (next) {
testPage.field.getText().then(function (text) {
expect(text).to.equal('expectedText');
});
});
}
then field is undefined. I have also tried adding getText() in the page file, but again get undefined or get told that I can't call 'then' on undefined.
In my mind, this should do exactly the same thing as the first example, but I'm far from an expert with Angular or JavaScript.
test.page.js looks like:
"use strict";
module.exports = (function () {
function TestPage() {
this.field = element(by.css('...'));
}
return TestPage;
});
Hoping someone can shine some light on why this is happening and what I should do instead to be able to put the CSS selector inside a page file for re-use.
Thanks
Your code new TestPage; returns the constructor TestPage, but it's never called.
You could return the class :
function TestPage() {
this.field = element(by.css('...'));
}
module.exports = TestPage;
var TestPage = require("...");
var testPage = new TestPage;
testPage.field.getText().then(...
Or an instance of the class:
function TestPage() {
this.field = element(by.css('...'));
}
module.exports = new TestPage();
var testPage = require("...");
testPage.field.getText().then(...
The way you defined re-usable element locators looks different. I am following some thing like below
Step 1: Define a .js file which should contain the Locator objects and re-usable methods
var Login = {
PageElements: {
emailInput: element(by.css('#email')),
passwordInput: element(by.css('#password')),
loginForm: element(by.css('#form')),
},
doLogin: function doLogin() {
this.PageElements.emailInput.sendKeys('blahblah#email.com');
this.PageElements.passwordInput.sendKeys('blahblah');
this.PageElements.loginForm.submit();
},
};
module.exports = Login;
Step 2: Call these page objects in your test classes.
var LoginPage = require('../pageobjects/LoginPage.js');
it('Scenario1_Login',function(){
LoginPage.PageElements.emailInput.sendKeys('blahblah');
});
More details here
I'm trying to sort out a good simple pattern for node.js with an init method for the use of 'models' when connecting to mongodb collections. Basically, each collection has a 'model'.
Here's what I have, setup as a singleton, any reason not go to with this method or is there more recommended method within the context of node?
module.exports = User;
function User () {
if ( arguments.callee.instance ) {
return arguments.callee.instance;
} else {
arguments.callee.instance = this;
}
//Init our database collection
}
User.findOne = function (user_id) {
}
User.addUser = function () {
}
return new User();
Thank you!
Um, you should put User.prototype.method.
User.prototype.findOne = function (user_id) {
}
User.prototype.addUser = function () {
}
Instead of 'return new User()' you probably meant,
module.exports = new User();
One reason not to export a 'new' User() is if you want to create more than one user in your nodejs program. If you only have one user, then a singleton is fine. Also, if you want to pass data to this module, you may want to do so via a constructor argument, and if you only construct the User in the module, then you can't pass to the constructor in your app.
I use a pattern that assigns module.exports to a function. The first argument of all my exports is an object shared amongst all exports, so they can add events/listeners and talk to each other in various different ways.
For example ('events' and 'app' are psuedo, not based on any real API),
function doLogin(app) {
return function (e) {
// some code to do login
}
}
module.exports = function login (app) {
app.events.on('login', doLogin(app));
}
Now all of the other modules can trigger a login via
app.events.login({'user': '..','pass': '..'});