Skip to content

Instantly share code, notes, and snippets.

@ajhekman
Last active March 28, 2017 21:16
Show Gist options
  • Save ajhekman/c24b407a7bc413699700fd19cdecca2d to your computer and use it in GitHub Desktop.
Save ajhekman/c24b407a7bc413699700fd19cdecca2d to your computer and use it in GitHub Desktop.
Computed Strict Showcase
import Ember from 'ember';
import computedStrict from '../computedStrict';
export default Ember.Component.extend({
firstName: 'John',
lastName: 'Doe',
middleInitial: "S",
fullName: computedStrict('firstName', 'lastName', function(firstN, lastN){
return firstN() + " " + lastN();
})
// Replace the fullName property with the below to see how computedStrict
// behaves
// Throws error `this.get` is not allowed
// fullName: computedStrict('firstName', 'lastName', function(firstN, lastN){
// return firstN() + " " + this.get('middleInitial') + " " + lastN();
// })
});
var handler = {
get: function(target, arg) {
if (arg === 'get') {
return function() {
throw new Error(
`You may not use 'this.get' in a strict computed property`
);
};
}
if (arg === 'computedStrict__unProxiedObject') {
return target;
}
if (arg === 'computedStrict__isAProxy') {
return true;
}
return target[arg];
}
};
function proxyIfPossible(value) {
if (value instanceof Ember.Object) {
return new Proxy(value, handler);
}
return value;
}
function unProxyIfNecessary(value) {
if (value.computedStrict__isAProxy) {
return value.computedStrict__unProxiedObject;
}
return value;
}
function getSingleProxiedDependency(object, name) {
var value = Ember.get(object, name);
return proxyIfPossible(value);
}
function getArrayProxiedDependency(object, arrayName, pieceName) {
return Ember.get(object, arrayName).map((part) => {
var piece = Ember.get(part, pieceName);
return proxyIfPossible(piece);
});
}
function getterForDependencyName(name) {
// Strip .[] -- it doesn't matter for getting.
name = name.replace(/\.\[\]$/, '');
// Split on @each, so we know if we must map.
var chunks = name.split('@each');
// If no @each, we're done -- just return the value.
if (chunks.length === 1) {
return () => {
return getSingleProxiedDependency(this, name);
};
}
// If there was an each, map and accumulate.
return () => {
return getArrayProxiedDependency(this, chunks[0], chunks[1]);
};
}
export default function computedStrict(...args) {
var fn = args[args.length - 1];
var names = args.slice(0, args.length - 1);
var wrapper = function() {
var values = names.map(getterForDependencyName, this);
var proxy = proxyIfPossible(this);
let computedReturn = fn.apply(proxy, values);
return unProxyIfNecessary(computedReturn);
};
var newArgs = names.concat([wrapper]);
return Ember.computed.apply(this, newArgs);
}
import Ember from 'ember';
export default Ember.Controller.extend({
appName: 'Ember Twiddle'
});
<br>
<br>
{{my-component}}
<br>
<br>
<h1>Computed Strict</h1>
<p>Open the console and review <code>components/my-component.js</code><br>to explore how <code>computedStrict</code> behaves when you try to break out of the Proxy.</p>
<hr>
First name: {{firstName}}<br>
Last name: {{lastName}}<br><br>
Full name (computedStrict): {{fullName}}<br>
{
"version": "0.12.1",
"EmberENV": {
"FEATURES": {}
},
"options": {
"use_pods": false,
"enable-testing": false
},
"dependencies": {
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.js",
"ember": "2.12.0",
"ember-template-compiler": "2.12.0",
"ember-testing": "2.12.0"
},
"addons": {
"ember-data": "2.12.1"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment