wrapMethod Meteor methods - javascript

I was looking into this presentation, building large meteor applications, and I like the idea of the wrapMethod(), but it seems like I can't use it like on the example.
Here is my code.
Meteor.methods({
'EX.Accounts.Methods.updateProfileData' : function(userId, firstName, secondName) {
check([firstName, secondName], [String]);
Meteor.users.update(userId, {
$set: {
'profile.firstName': firstName,
'profile.lastName': secondName,
'profile.isRegisted': true
}
});
}
});
EX.Accounts.Methods.updateUserProfile = EX.wrapMethod('EX.Accounts.Methods.updateProfileData');
But I got this error.
TypeError: Object # has no method 'wrapMethod'
I'm missing something I know but just can't find any information about this "wrapMethod"
Update
Also try with
_.extend(EX.Accounts.Methods,{
updateUserProfile : EX.Accounts.Methods.updateProfileData
});
Which doesn't return an error but I don't see the method on the global namespace.
EX.Accounts.Methods is clear with no methods.

I think the developer created the method wrapMethod on his PB obejct. As you can see here there is nothing called wrapMethod in Meteor. I guess they wrote something like this:
PB.wrapMethod = function wrapMethod (meteorMethod) {
return function wrappedMeteorMethod (/*arugments*/) {
Meteor.apply(meteorMethod, arguments)
}
}
I think it's kinda neat.
Btw.: As you can see i like to name my anonymous functions. Makes debugging nicer.

In ES6 this becomes a beauty:
wrapMethod(method) {
return (...args) => Meteor.call(method, ...args);
}

Related

Nesting helper functions inside a function for readability purposes

So I am currently reading through Clean Code and I really like the idea of super small functions that each tell their own "story". I also really like the way he puts how code should be written to be read in terms of "TO paragraphs", which I've decided to kind of rename in my head to "in order to"
Anyway I have been refactoring alot of code to include more meaningful names and to make the flow in which it will be read a little better and I have stumbled into something that I am unsure on and maybe some gurus here could give me some solid advice!
I know that code-styles is a highly controversial and subjective topic, but hopefully I wont get reamed out by this post.
Thanks everyone!
PSA: I am a noob, fresh out of College creating a web app using the MEAN stack for an internal project in an internship at the moment.
Clean Code refactor
//Modal Controller stuff above. vm.task is an instance variable
vm.task = vm.data.task;
castTaskDataTypesForForm();
function castTaskDataTypesForForm() {
castPriorityToInt();
castReminderInHoursToInt();
castDueDateToDate();
getAssigneObjFromAssigneeString();
}
function castPriorityToInt() {
vm.task.priority = vm.task.priority === undefined ?
0 : parseInt(vm.task.priority);
}
function castReminderInHoursToInt() {
vm.task.reminderInHours = vm.task.reminderInHours === undefined ?
0 : parseInt(vm.task.reminderInHours);
}
function castDueDateToDate() {
vm.task.dueDate = new Date(vm.task.dueDate);
}
function getAssigneObjFromAssigneeString() {
vm.task.assignee = getUserFromId(vm.task.assignee);
}
Possibly better refactor? / My question ----------------------------
//Modal Controller stuff above. vm.task is an instance variable
vm.task = vm.data.task;
castTaskDataTypesForForm();
function castTaskDataTypesForForm() {
castPriorityToInt();
castReminderInHoursToInt();
castDueDateToDate();
getAssigneObjFromAssigneeString();
function castPriorityToInt() {
vm.task.priority = vm.task.priority === undefined ?
0 : parseInt(vm.task.priority);
}
function castReminderInHoursToInt() {
vm.task.reminderInHours = vm.task.reminderInHours === undefined ?
0 : parseInt(vm.task.reminderInHours);
}
function castDueDateToDate() {
vm.task.dueDate = new Date(vm.task.dueDate);
}
function getAssigneObjFromAssigneeString() {
vm.task.assignee = getUserFromId(vm.task.assignee);
}
}
Posting the IIFE example here so I have more room to work with. I'm not saying this is the best option, it's the one I would use with the info the OP gave us.
var castTaskDataTypesForForm = (function() {
var castPriorityToInt = function castPriorityToInt() { ... },
castReminderInHoursToInt = function castReminderInHoursToInt() { .. },
castDueDateToDate = function castDueDateToDate() { ... },
getAssigneObjFromAssigneeString = function getAssigneObjFromAssigneeString() { ... };
return function castTaskDataTypesForForm() {
castPriorityToInt();
castReminderInHoursToInt();
castDueDateToDate();
getAssigneObjFromAssigneeString();
};
}());
vm.task = vm.data.task;
castTaskDataTypesForForm();
This way the helper functions only get defined once and are kept private inside the closure. You can obv remove the var x = function x syntax if you prefer the function x() style.
edit: If the function only gets called once, your own examples are probably the cleaner code. The reason you'd use the IIFE syntax would be to keep the helper functions only accesible by the main function, like in your own second example.
MEANjs uses the second method sometimes (with callbacks for example). I personally think it's nice if you are not intending to use those helpers outside of the main function.

How to test that one function is called before another

I have some tightly coupled legacy code that I want to cover with tests. Sometimes it's important to ensure that one mocked out method is called before another. A simplified example:
function PageManager(page) {
this.page = page;
}
PageManager.prototype.openSettings = function(){
this.page.open();
this.page.setTitle("Settings");
};
In the test I can check that both open() and setTitle() are called:
describe("PageManager.openSettings()", function() {
beforeEach(function() {
this.page = jasmine.createSpyObj("MockPage", ["open", "setTitle"]);
this.manager = new PageManager(this.page);
this.manager.openSettings();
});
it("opens page", function() {
expect(this.page.open).toHaveBeenCalledWith();
});
it("sets page title to 'Settings'", function() {
expect(this.page.setTitle).toHaveBeenCalledWith("Settings");
});
});
But setTitle() will only work after first calling open(). I'd like to check that first page.open() is called, followed by setTitle(). I'd like to write something like this:
it("opens page before setting title", function() {
expect(this.page.open).toHaveBeenCalledBefore(this.page.setTitle);
});
But Jasmine doesn't seem to have such functionality built in.
I can hack up something like this:
beforeEach(function() {
this.page = jasmine.createSpyObj("MockPage", ["open", "setTitle"]);
this.manager = new PageManager(this.page);
// track the order of methods called
this.calls = [];
this.page.open.and.callFake(function() {
this.calls.push("open");
}.bind(this));
this.page.setTitle.and.callFake(function() {
this.calls.push("setTitle");
}.bind(this));
this.manager.openSettings();
});
it("opens page before setting title", function() {
expect(this.calls).toEqual(["open", "setTitle"]);
});
This works, but I'm wondering whether there is some simpler way to achieve this. Or some nice way to generalize this so I wouldn't need to duplicate this code in other tests.
PS. Of course the right way is to refactor the code to eliminate this kind of temporal coupling. It might not always be possible though, e.g. when interfacing with third party libraries. Anyway... I'd like to first cover the existing code with tests, modifying it as little as possible, before delving into further refactorings.
I'd like to write something like this:
it("opens page before setting title", function() {
expect(this.page.open).toHaveBeenCalledBefore(this.page.setTitle);
});
But Jasmine doesn't seem to have such functionality built in.
Looks like the Jasmine folks saw this post, because this functionality exists. I'm not sure how long it's been around -- all of their API docs back to 2.6 mention it, though none of their archived older style docs mention it.
toHaveBeenCalledBefore(expected)
expect the actual value (a Spy) to have been called before another Spy.
Parameters:
Name Type Description
expected Spy Spy that should have been called after the actual Spy.
A failure for your example looks like Expected spy open to have been called before spy setTitle.
Try this:
it("setTitle is invoked after open", function() {
var orderCop = jasmine.createSpy('orderCop');
this.page.open = jasmine.createSpy('openSpy').and.callFake(function() {
orderCop('fisrtInvoke');
});
this.page.setTitle = jasmine.createSpy('setTitleSpy').and.callFake(function() {
orderCop('secondInvoke');
});
this.manager.openSettings();
expect(orderCop.calls.count()).toBe(2);
expect(orderCop.calls.first().args[0]).toBe('firstInvoke');
expect(orderCop.calls.mostRecent().args[0]).toBe('secondInvoke');
}
EDIT: I just realized my original answer is effectively the same as the hack you mentioned in the question but with more overhead in setting up a spy. It's probably simpler doing it with your "hack" way:
it("setTitle is invoked after open", function() {
var orderCop = []
this.page.open = jasmine.createSpy('openSpy').and.callFake(function() {
orderCop.push('fisrtInvoke');
});
this.page.setTitle = jasmine.createSpy('setTitleSpy').and.callFake(function() {
orderCop.push('secondInvoke');
});
this.manager.openSettings();
expect(orderCop.length).toBe(2);
expect(orderCop[0]).toBe('firstInvoke');
expect(orderCop[1]).toBe('secondInvoke');
}
Create a fake function for the second call that expects the first call to have been made
it("opens page before setting title", function() {
// When page.setTitle is called, ensure that page.open has already been called
this.page.setTitle.and.callFake(function() {
expect(this.page.open).toHaveBeenCalled();
})
this.manager.openSettings();
});
Inspect the specific calls by using the .calls.first() and .calls.mostRecent() methods on the spy.
Basically did the same thing. I felt confident doing this because I mocked out the function behaviors with fully synchronous implementations.
it 'should invoke an options pre-mixing hook before a mixin pre-mixing hook', ->
call_sequence = []
mix_opts = {premixing_hook: -> call_sequence.push 1}
#mixin.premixing_hook = -> call_sequence.push 2
spyOn(mix_opts, 'premixing_hook').and.callThrough()
spyOn(#mixin, 'premixing_hook').and.callThrough()
class Example
Example.mixinto_proto #mixin, mix_opts, ['arg1', 'arg2']
expect(mix_opts.premixing_hook).toHaveBeenCalledWith(['arg1', 'arg2'])
expect(#mixin.premixing_hook).toHaveBeenCalledWith(['arg1', 'arg2'])
expect(call_sequence).toEqual [1, 2]
Lately I've developed a replacement for Jasmine spies, called strict-spies, which solves this problem among many others:
describe("PageManager.openSettings()", function() {
beforeEach(function() {
this.spies = new StrictSpies();
this.page = this.spies.createObj("MockPage", ["open", "setTitle"]);
this.manager = new PageManager(this.page);
this.manager.openSettings();
});
it("opens page and sets title to 'Settings'", function() {
expect(this.spies).toHaveCalls([
["open"],
["setTitle", "Settings"],
]);
});
});

javascript function parameter place

How to write function(object) with 2 methods (alert and console.log) to be able to use it like this:
fname("text").alert //-now text is alerted;
fname("text").cons //-now text shows in console log.
the methods are not important byt the way of execution. I know that it must be self invoiking function but i cant do it. I dont want to use it this way - fname.alert("text").
Greetings
Kriss
It's not possible in any sane way that works everywhere. The example you posted would require you to define an accessor for those properties - and that only works with modern JS engines.
Anyway, here's code that would actually do this. But please do not use this in any real application! See the last code block for a better solution
function fname(message) {
var obj = {};
Object.defineProperty(obj, 'alert', {
get: function() {
alert(message);
}
});
Object.defineProperty(obj, 'cons', {
get: function() {
console.log(message);
}
});
return obj;
}
This works because fname('hello').alert will cause the getter function for the alert property to be executed - and while such a function should usually return a value there's nothing to stop it from doing something like showing an alert() message.
What you could achieve in a way that works everywhere would be something like that though:
fname('text').alert();
fname('text').cons();
This could be done like this:
function fname(message) {
return {
alert: function() {
alert(message);
},
cons: function() {
console.log(message);
}
}
}
function fname(str) {
return {
alert:function(){alert(str)},
cons:function(){console.log(str)}
}
}
Doing fname("text").alert() alerts text.

Referencing Other Functions from Name Spaced JavaScript

So I am trying to consolidate a bunch of code into some nice NameSpaced functions, but am having a tough time getting it to all work together. For example, I have this (edited down for clarity):
YW.FB = function() {
return {
init: function(fncSuc, fncFail) {
FB.init(APIKey, "/services/fbconnect/xd_receiver.htm");
FB.Bootstrap.requireFeatures(["Connect"]);
if(typeof fncSuc=='function') fncSuc();
},
login: function(fncSuc) {
this.FB.Connect.requireSession(function() {
if(typeof fncSuc=='function') fncSuc();
});
},
getUserInfo: function() {
var userInfo = new Object;
FB.Facebook.apiClient.users_getInfo([FB.Facebook.apiClient.get_session().uid],["name"],function(result, ex){
userInfo.name = result[0]['name'];
userInfo.uid = result[0]['uid'];
userInfo.url = FBName.replace(/\s+/g, '-');
return userInfo;
})
}
};
}();
On a normal page I can just do:
FB.init(APIKey, "/services/fbconnect/xd_receiver.htm");
FB.Bootstrap.requireFeatures(["Connect"]);
var userInfo = new Object;
FB.Facebook.apiClient.users_getInfo([FB.Facebook.apiClient.get_session().uid],["name"],function(result, ex){
userInfo.name = result[0]['name'];
userInfo.uid = result[0]['uid'];
userInfo.url = FBName.replace(/\s+/g, '-');
return userInfo;
})
And it works.
I have been trying to do:
YW.init();
YW.login();
YW.getUserInfo();
But it doesn't work. I keep getting 'FB.Facebook is undefined' from YW.getUserInfo
I could be doing this all wrong too. So the FB.init, FB.Facebook stuff is using the facebook connect libraries. Am I doing this all wrong?
If you look at the JavaScript that your browser has parsed in Firebug or a similar web debugger do you see the Facebook Connect JavaScript there? Looks like it's not in scope, and since FB is at the global level that means it's not in scope at all. Has nothing to do with namespaces. Global in JavaScript is global everywhere.

Overriding a JavaScript function while referencing the original

I have a function, a(), that I want to override, but also have the original a() be performed in an order depending on the context. For example, sometimes when I'm generating a page I'll want to override like this:
function a() {
new_code();
original_a();
}
and sometimes like this:
function a() {
original_a();
other_new_code();
}
How do I get that original_a() from within the over-riding a()? Is it even possible?
Please don't suggest alternatives to over-riding in this way, I know of many. I'm asking about this way specifically.
You could do something like this:
var a = (function() {
var original_a = a;
if (condition) {
return function() {
new_code();
original_a();
}
} else {
return function() {
original_a();
other_new_code();
}
}
})();
Declaring original_a inside an anonymous function keeps it from cluttering the global namespace, but it's available in the inner functions.
Like Nerdmaster mentioned in the comments, be sure to include the () at the end. You want to call the outer function and store the result (one of the two inner functions) in a, not store the outer function itself in a.
The Proxy pattern might help you:
(function() {
// log all calls to setArray
var proxied = jQuery.fn.setArray;
jQuery.fn.setArray = function() {
console.log( this, arguments );
return proxied.apply( this, arguments );
};
})();
The above wraps its code in a function to hide the "proxied"-variable. It saves jQuery's setArray-method in a closure and overwrites it. The proxy then logs all calls to the method and delegates the call to the original. Using apply(this, arguments) guarantees that the caller won't be able to notice the difference between the original and the proxied method.
Thanks guys the proxy pattern really helped.....Actually I wanted to call a global function foo..
In certain pages i need do to some checks. So I did the following.
//Saving the original func
var org_foo = window.foo;
//Assigning proxy fucnc
window.foo = function(args){
//Performing checks
if(checkCondition(args)){
//Calling original funcs
org_foo(args);
}
};
Thnx this really helped me out
You can override a function using a construct like:
function override(f, g) {
return function() {
return g(f);
};
}
For example:
a = override(a, function(original_a) {
if (condition) { new_code(); original_a(); }
else { original_a(); other_new_code(); }
});
Edit: Fixed a typo.
Passing arbitrary arguments:
a = override(a, function(original_a) {
if (condition) { new_code(); original_a.apply(this, arguments) ; }
else { original_a.apply(this, arguments); other_new_code(); }
});
The answer that #Matthew Crumley provides is making use of the immediately invoked function expressions, to close the older 'a' function into the execution context of the returned function. I think this was the best answer, but personally, I would prefer passing the function 'a' as an argument to IIFE. I think it is more understandable.
var a = (function(original_a) {
if (condition) {
return function() {
new_code();
original_a();
}
} else {
return function() {
original_a();
other_new_code();
}
}
})(a);
The examples above don't correctly apply this or pass arguments correctly to the function override. Underscore _.wrap() wraps existing functions, applies this and passes arguments correctly. See: http://underscorejs.org/#wrap
In my opinion the top answers are not readable/maintainable, and the other answers do not properly bind context. Here's a readable solution using ES6 syntax to solve both these problems.
const orginial = someObject.foo;
someObject.foo = function() {
if (condition) orginial.bind(this)(...arguments);
};
I had some code written by someone else and wanted to add a line to a function which i could not find in the code. So as a workaround I wanted to override it.
None of the solutions worked for me though.
Here is what worked in my case:
if (typeof originalFunction === "undefined") {
originalFunction = targetFunction;
targetFunction = function(x, y) {
//Your code
originalFunction(a, b);
//Your Code
};
}
I've created a small helper for a similar scenario because I often needed to override functions from several libraries. This helper accepts a "namespace" (the function container), the function name, and the overriding function. It will replace the original function in the referred namespace with the new one.
The new function accepts the original function as the first argument, and the original functions arguments as the rest. It will preserve the context everytime. It supports void and non-void functions as well.
function overrideFunction(namespace, baseFuncName, func) {
var originalFn = namespace[baseFuncName];
namespace[baseFuncName] = function () {
return func.apply(this, [originalFn.bind(this)].concat(Array.prototype.slice.call(arguments, 0)));
};
}
Usage for example with Bootstrap:
overrideFunction($.fn.popover.Constructor.prototype, 'leave', function(baseFn, obj) {
// ... do stuff before base call
baseFn(obj);
// ... do stuff after base call
});
I didn't create any performance tests though. It can possibly add some unwanted overhead which can or cannot be a big deal, depending on scenarios.
So my answer ended up being a solution that allows me to use the _this variable pointing to the original object.
I create a new instance of a "Square" however I hated the way the "Square" generated it's size. I thought it should follow my specific needs. However in order to do so I needed the square to have an updated "GetSize" function with the internals of that function calling other functions already existing in the square such as this.height, this.GetVolume(). But in order to do so I needed to do this without any crazy hacks. So here is my solution.
Some other Object initializer or helper function.
this.viewer = new Autodesk.Viewing.Private.GuiViewer3D(
this.viewerContainer)
var viewer = this.viewer;
viewer.updateToolbarButtons = this.updateToolbarButtons(viewer);
Function in the other object.
updateToolbarButtons = function(viewer) {
var _viewer = viewer;
return function(width, height){
blah blah black sheep I can refer to this.anything();
}
};
Not sure if it'll work in all circumstances, but in our case, we were trying to override the describe function in Jest so that we can parse the name and skip the whole describe block if it met some criteria.
Here's what worked for us:
function describe( name, callback ) {
if ( name.includes( "skip" ) )
return this.describe.skip( name, callback );
else
return this.describe( name, callback );
}
Two things that are critical here:
We don't use an arrow function () =>.
Arrow functions change the reference to this and we need that to be the file's this.
The use of this.describe and this.describe.skip instead of just describe and describe.skip.
Again, not sure it's of value to anybody but we originally tried to get away with Matthew Crumley's excellent answer but needed to make our method a function and accept params in order to parse them in the conditional.

Categories

Resources