Browse Source

cowWorkshop

Herbert Vojčík 7 years ago
parent
commit
d09e810ac3
3 changed files with 87 additions and 1 deletions
  1. 49 1
      README.md
  2. 25 0
      lib/cow-value-model.js
  3. 13 0
      src/cow-value-model.js

+ 49 - 1
README.md

@@ -133,7 +133,14 @@ composeReducers(
 
 Creates an overloaded function allowing
 to set or get specified key from any object.
-Get when one arg, set when two args.
+
+It gets when one arg passed, sets when two args passed.
+Setting `undefined` ends up as plain get
+(ES2015 default arguments semantics),
+so props are not created when not present
+if setting `undefined`; other values including `null` are ok
+and create nonpresent props.
+
 Specify keys by passing a list of keys to `cowValueModel`.
 Key can be either:
  - number
@@ -205,3 +212,44 @@ but it also allows you to use `case answerQuestion.TYPE:` in your reducer,
 since `answerQuestion.TYPE === "answer question"`.
 IOW, this removes the two-space problem of having `const FOO_BAR_TYPE`
 as well as `fooBar` action creator.
+
+### `cowWorkshop(keys, fn = x => x)(obj, [options])`
+
+This is multipurpose enumerate-and-act function to manipulate objects
+using `cowValueModel`. The `options` argument can contain these additional fields:
+  - `result` -- where to put elements (`obj` by default),
+  - `resultKeys` -- what keys to use to put into `result` (`keys` by default)
+  - `diff` -- where to put diffing elements (`undefined` by default)
+
+Function enumerates over keys and performs
+"get key from obj, call fn on value, put transformed value into resultKey in result"
+operations over them, using `cowValueModel` for getting as well as putting.
+Additionally, if putting actually resulted in change,
+the result key and value is also put into `diff`.
+It then returns `{result, diff}` object.
+
+```js
+cowWorkshop(["a", "b.c"])();
+// does nothing
+// => {result: undefined, diff: undefined}
+  
+cowWorkshop(["a", "b.c"], () => null)();
+// sets a and b.c to null
+// => {result: {a: null, b: {c: null}}, diff: {a: null, b: {c: null}}}
+  
+const data = {a: 'foo', b: {c: null}};
+cowWorkshop(["a", "b.c"], JSON.stringify)(data);
+// changes a and b.c to string representation; change to a is noop
+// => {result: {a: 'foo', b: {c: 'null'}}, diff: {b: {c: 'null'}}}
+  
+const stored = {ay: 'bar', beecee: 'baz', cee: 'quux'};
+const data = {a: 'foo', b: {c: null}};
+cowWorkshop(["a", "b.c"])(data, {result: stored, resultKeys: ["ay", "beecee"]});
+// "copies" a and b.c into `stored` under different keys
+// => {result: {ay: 'foo', beecee: null, cee: 'quux'}, diff: {ay: 'foo', beecee: null}}
+  
+const data = {a: 'foo', b: {c: 'bar'}, c: 'quux'};
+cowWorkshop(["a", "b.c"], () => null)(data);
+// "nulls" a few fields
+// => {result: {a: null, b: {c: null}, c: 'quux'}, diff: {a: null, b: {c: null}}}
+```

+ 25 - 0
lib/cow-value-model.js

@@ -51,4 +51,29 @@ var cowValueModel = exports.cowValueModel = function cowValueModel() {
             return x[key];
         }, obj) : setField(obj, 0, val);
     };
+};
+
+var cowWorkshop = exports.cowWorkshop = function cowWorkshop(keys) {
+    var fn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function (x) {
+        return x;
+    };
+    return function (obj) {
+        var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
+            _ref$result = _ref.result,
+            result = _ref$result === undefined ? obj : _ref$result,
+            _ref$resultKeys = _ref.resultKeys,
+            resultKeys = _ref$resultKeys === undefined ? keys : _ref$resultKeys,
+            diff = _ref.diff;
+
+        keys.forEach(function (key, index) {
+            var value = fn(cowValueModel(key)(obj));
+            var modifier = cowValueModel(resultKeys[index]);
+            var oldDst = result;
+            result = modifier(oldDst, value);
+            if (result !== oldDst) {
+                diff = modifier(diff, value);
+            }
+        });
+        return { result: result, diff: diff };
+    };
 };

+ 13 - 0
src/cow-value-model.js

@@ -32,3 +32,16 @@ export const cowValueModel = (...keyDescriptions) => {
             keys.reduce((x = {}, key) => x[key], obj) :
             setField(obj, 0, val);
 };
+
+export const cowWorkshop = (keys, fn = x => x) => (obj, {result = obj, resultKeys = keys, diff} = {}) => {
+    keys.forEach((key, index) => {
+        const value = fn(cowValueModel(key)(obj));
+        const modifier = cowValueModel(resultKeys[index]);
+        const oldDst = result;
+        result = modifier(oldDst, value);
+        if (result !== oldDst) {
+            diff = modifier(diff, value);
+        }
+    });
+    return {result, diff};
+};