From 8c1b0224d7e5a299afb5c655ee795c37f05278ed Mon Sep 17 00:00:00 2001 From: Kelly Selden Date: Mon, 25 Sep 2017 23:23:47 +0200 Subject: [PATCH] add hotfix for composing class computed --- addon/create-class-computed.js | 24 ++++++++++++++--- addon/flatten-keys.js | 8 ++++++ tests/acceptance/application-test.js | 16 +++++++++++- tests/dummy/app/controllers/application.js | 26 ++++++++++++++++--- tests/dummy/app/templates/application.hbs | 4 ++- .../integration/create-class-computed-test.js | 2 +- tests/unit/create-class-computed-test.js | 6 ++--- 7 files changed, 73 insertions(+), 13 deletions(-) diff --git a/addon/create-class-computed.js b/addon/create-class-computed.js index 9939037..be88a38 100644 --- a/addon/create-class-computed.js +++ b/addon/create-class-computed.js @@ -97,17 +97,27 @@ export default function(observerBools, macroGenerator) { } let mappedKeys = []; + let originalKeys = []; - function rewriteComputed(obj, key) { - let mappedWithResolvedOberverKeys = mappedKeys.map((macro, i) => { + function createComputed(keys, context, key) { + let resolvedOberverKeys = keys.map((macro, i) => { let shouldObserve = observerBools[i]; if (shouldObserve) { - macro = getValue({ context: this, macro, key }); + // succeeds with `raw`, fails with everything else + try { + macro = getValue({ context, macro, key }); + } catch (err) { + macro = undefined; + } } return macro; }); - let cp = macroGenerator.apply(this, mappedWithResolvedOberverKeys); + return macroGenerator.apply(context, resolvedOberverKeys); + } + + function rewriteComputed(obj, key) { + let cp = createComputed(mappedKeys, this, key); defineProperty(this, 'computed', cp); } @@ -121,6 +131,7 @@ export default function(observerBools, macroGenerator) { let mappedKey = resolveMappedLocation(key, i); + originalKeys.push(key); mappedKeys.push(mappedKey); if (shouldObserve) { classProperties[`key${i}DidChange`] = observer(mappedKey, rewriteComputed); @@ -150,6 +161,11 @@ export default function(observerBools, macroGenerator) { return get(propertyInstance, 'computed'); }).readOnly(); + // workaround for watching array and object rewriting properties + // in class computed scope while composing macros + // ex `first(filterBy('arr', 'prop'))` + cp._classComputed = createComputed(originalKeys); + return cp; }; } diff --git a/addon/flatten-keys.js b/addon/flatten-keys.js index c3c72a0..d3081ba 100644 --- a/addon/flatten-keys.js +++ b/addon/flatten-keys.js @@ -8,6 +8,14 @@ function flattenKey(key, flattenedKeys) { return; } + // workaround for watching array and object rewriting properties + // in class computed scope while composing macros + // ex `first(filterBy('arr', 'prop'))` + let classComputed = key._classComputed; + if (classComputed) { + dependentKeys = classComputed._dependentKeys; + } + return _flattenKeys(dependentKeys, flattenedKeys); } diff --git a/tests/acceptance/application-test.js b/tests/acceptance/application-test.js index 51d4bd7..2bb60a7 100644 --- a/tests/acceptance/application-test.js +++ b/tests/acceptance/application-test.js @@ -10,9 +10,23 @@ test('double render failing test', function(assert) { assert.equal(find('.computed').text(), 'test val 1'); }); - click('button'); + click('.button'); andThen(function() { assert.equal(find('.computed').text(), 'test val 2'); }); }); + +test('class computed array macro inside a normal array macro, handles pushes', function(assert) { + visit('/'); + + andThen(function() { + assert.equal(find('.computed2').text(), '1'); + }); + + click('.button2'); + + andThen(function() { + assert.equal(find('.computed2').text(), '3'); + }); +}); diff --git a/tests/dummy/app/controllers/application.js b/tests/dummy/app/controllers/application.js index 90c106d..28e2678 100644 --- a/tests/dummy/app/controllers/application.js +++ b/tests/dummy/app/controllers/application.js @@ -1,22 +1,31 @@ import Controller from '@ember/controller'; -import EmberObject, { set } from '@ember/object'; +import EmberObject, { get, set } from '@ember/object'; import { A as emberA } from '@ember/array'; import { readOnly } from '@ember/object/computed'; import createClassComputed from 'ember-macro-helpers/create-class-computed'; import computed from 'ember-macro-helpers/computed'; +import raw from 'ember-macro-helpers/raw'; +import normalizeArrayKey from 'ember-macro-helpers/normalize-array-key'; const getBy = createClassComputed( [false, true], (obj, key) => readOnly(`${obj}.${key}`) ); +const filterBy = createClassComputed( + [false, true], + (arr, key, val) => computed(normalizeArrayKey(arr, [key]), val, (arr, val) => arr.filterBy(key, val)) +); + export default Controller.extend({ array: emberA([ EmberObject.create({ - testProp: 'test val 1' + testProp: 'test val 1', + testProp2: 1 }), EmberObject.create({ - testProp: 'test val 2' + testProp: 'test val 2', + testProp2: 2 }) ]), index: 0, @@ -27,9 +36,20 @@ export default Controller.extend({ 'testProp' ), + computed2: computed( + filterBy('array', 'testProp', raw('test val 1')), + array => get(array[array.length - 1], 'testProp2') + ), + actions: { update() { set(this, 'index', 1); + }, + update2() { + get(this, 'array').pushObject(EmberObject.create({ + testProp: 'test val 1', + testProp2: 3 + })); } } }); diff --git a/tests/dummy/app/templates/application.hbs b/tests/dummy/app/templates/application.hbs index c7af736..0f034dc 100644 --- a/tests/dummy/app/templates/application.hbs +++ b/tests/dummy/app/templates/application.hbs @@ -1,3 +1,5 @@
{{computed}}
+
{{computed2}}
- \ No newline at end of file + + \ No newline at end of file diff --git a/tests/integration/create-class-computed-test.js b/tests/integration/create-class-computed-test.js index aaede91..27640bf 100644 --- a/tests/integration/create-class-computed-test.js +++ b/tests/integration/create-class-computed-test.js @@ -21,7 +21,7 @@ module('Integration | create class computed', { filterBy = createClassComputed( [false, true], function(array, key, value) { - if (!key) { + if (!key && this) { PROPERTIES.set(this, array.split('.').reverse()[0]); } return computed(normalizeArrayKey(array, [key]), value, function(array, value) { diff --git a/tests/unit/create-class-computed-test.js b/tests/unit/create-class-computed-test.js index d08f88f..c094b93 100644 --- a/tests/unit/create-class-computed-test.js +++ b/tests/unit/create-class-computed-test.js @@ -141,13 +141,13 @@ test('it rewrites when observer changes', function(assert) { } }); - assert.equal(observerCallback.callCount, 2); + assert.equal(observerCallback.callCount, 3); assert.equal(callback.callCount, 2); subject.set('test5', 'test6'); - assert.equal(observerCallback.callCount, 3); + assert.equal(observerCallback.callCount, 4); subject.get('computed'); @@ -157,7 +157,7 @@ test('it rewrites when observer changes', function(assert) { subject.get('computed'); - assert.equal(observerCallback.callCount, 3); + assert.equal(observerCallback.callCount, 4); assert.equal(callback.callCount, 4); });