Create a gist now

Instantly share code, notes, and snippets.

JavaScript implementation of Ruby2.0 Refinements.
var Refinements = {};
Refinements.modules = {};
Refinements.register = function(name, fn) {
Refinements.modules[name] = fn;
};
Refinements.using = function() {
var args = Array.prototype.slice.call(arguments);
var fn = args.pop();
var saveList = [];
args.forEach(function(name) {
var moduleFn = Refinements.modules[name];
if (typeof moduleFn !== 'function') return;
moduleFn(function refine(obj, props) {
Object.keys(props).forEach(function(propName) {
saveList.push({
obj: obj,
propName: propName
});
if (propName in obj) {
saveList[saveList.length - 1].origVal = obj[propName];
}
obj[propName] = props[propName];
});
});
});
fn();
saveList.forEach(function(save) {
var obj = save.obj;
var propName = save.propName;
if ('origVal' in save) {
obj[propName] = save.origVal;
}
else {
delete obj[propName];
}
});
};
Refinements.register('TestRefine', function(refine) {
refine(Array.prototype, {
sample: function() {
var index = Math.floor(Math.random() * this.length);
return this[index];
}
});
refine(String.prototype, {
greeting: function() {
return 'Hello ' + this + '!';
}
});
});
function MyClass() {}
MyClass.prototype.foo = function() {
return 'foo!';
};
Refinements.register('RefineMyClass', function(refine) {
refine(MyClass.prototype, {
foo: function() {
return 'bar!';
}
});
});
var arr = [1, 2, 3, 4];
var obj = new MyClass();
Refinements.using('TestRefine', 'RefineMyClass', function() {
console.log(arr.sample()); //=> pickup random element
console.log('5509'.greeting()); //=> Hello 5509!
console.log(obj.foo()); //=> bar!
});
try {
console.log(obj.foo()); //=> foo!
console.log(arr.sample()); // Error(Object has no method 'sample'
}
catch (e) {
console.log(e);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment