Firstly, what’s gedi?
git: https://github.com/gaffa-tape/gedi
npm: https://npmjs.org/package/gedi
Gedi is model API wrapper. It Allows you to get and set, and remove to/from an object, and bind to changes that occur due to sets/removes.
Simple usage:
// Set up the models data var model = new Gedi({ thing: 2, lifeforms:{ dogs:[ { name: "scruffy", age:8 }, { name: "spot", age:4 } ], users:[ { name: "bob", age: 20 }, { name: "john", age:45 } ] } }); // get model.get('[thing]'); // --> 2 // set model.set('[thing]', 5); // get after set model.get('[thing]'); // --> 5 // bind to [thing] model.bind('[thing]', function(event){ // this callback is called when [thing] changes. // event.getValue() returns the value of [thing] });
You can throw a parent path on the end of get/set/etc.. to make all bindings relative to it.
model.get('[dogs]'); // --> undefined model.get('[lifeforms/dogs]'); // --> Array of dogs. // here, [dogs] will be relative to [lifeforms] model.get('[dogs]', '[lifeforms]'); // --> Array of dogs.
Why square braces?
Because gedi is more powerfull than just an object watcher.
you can pull data out via expressions…
model.get('(last [lifeforms/dogs]).name'); // --> "spot"
And even bind callbacks to expressions…
model.bind('(last [lifeforms/dogs]).name', function(event){ // this callback is called when [lifeforms/dogs] changes. // event.getValue() returns the value of (last [lifeforms/dogs]).name });
However there was one thing I’d always thought would be awesome, and i’ve recently made some pretty big changes to how gedi works under the covers to allow.
// Set the last item in [lifeforms/dogs] to a different dog model.set('(last [lifeforms/dogs])', {name: "ellie", age: 2});
Gedi can now keep track of paths throughout the execution of an expression, and perform useful opperations using the resulting path.
This is pretty exciting to me, expecially for how it can be used in gaffa.
You can also perform opperations on the result of a filter/map/slice/concat/etc.. eg.
(fyi, the syntax for an anonymous function in gedi is {param1 param2 paramN functionBody})
remove all items in an array that match an expression.
model.remove('(filter [dogs] {dog (> dog.age 7)})', '[lifeforms]');
set properties on all items across multiple arrays that match an expression. (TO RIDICULOUS, AND BEYOND!)
model.set('(map (filter (concat [dogs] [users]) {item (> item.age 5)}) {item item.label})', 'old!', '[lifeforms]');
And of course, any changes made using expressions cause model events to fire at the right paths.