Skip to content

Instantly share code, notes, and snippets.

@radiosilence
Last active August 29, 2015 14:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save radiosilence/11200116 to your computer and use it in GitHub Desktop.
Save radiosilence/11200116 to your computer and use it in GitHub Desktop.
Versioned repository pattern for JS

Versioned repository pattern for JS, for use with ReactJS. Obscenely fast, and would recommend actually using TypeScript instead of imitating it's rather great class system. Basically in a real app, you'd inject services with dependency injection and talk to them that way. The repositories could then handle syncing with a remote endpoint as opposed to just maintaining a list. It's very WIP at the moment, but the idea was to create a separation of concerns and decouple models from the components themselves. I will re-write this in TypeScript at some point so it's less ugly, but didn't have it set up on my home desktop.

<!doctype html>
<html>
<head>
</head>
<body>
<div id="main" />
<script src=http://cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.min.js></script>
<script src=http://cdnjs.cloudflare.com/ajax/libs/react/0.10.0/JSXTransformer.js></script>
<script src=http://cdnjs.cloudflare.com/ajax/libs/react/0.10.0/react-with-addons.min.js></script>
<script type="text/jsx">
/**
* @jsx React.DOM
*/
"use strict";
window.updates = 0;
var ratId = 0, toyId = 0;
// Stolen from TypeScript
var __extends = this.__extends || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
__.prototype = b.prototype;
d.prototype = new __();
};
var Versioned = (function() {
function Versioned() {
this.__version = 0;
}
Versioned.prototype.update = function(k, v) {
this.__version++;
this[k] = v;
}
Versioned.prototype.bump = function() {
this.__version++;
}
return Versioned;
})();
var Rat = (function(_super) {
__extends(Rat, _super);
function Rat(name, color, toys) {
_super.call(this);
this.id = ++ratId;
this.name = name;
this.color = color;
this.toys = toys;
}
Rat.prototype.squeek = function() {
return "Eeep! I'm " + name;
}
Rat.prototype.toString = function() {
return [this.name, 'the', this.color, 'rattie'].join(' ');
}
return Rat;
})(Versioned);
var Toy = (function(_super) {
__extends(Toy, _super);
function Toy(name) {
_super.call(this);
this.id = ++toyId;
this.name = name;
}
return Toy;
})(Versioned);
var BaseRepository = (function(_super) {
function BaseRepository(items) {
_super.call(this);
this.items = items;
this.index ={
id: {}
};
for (var i = 0, j = this.items.length; i !== j; i++) {
var item = this.items[i];
this.index.id[item.id] = {
item: item,
index: i
}
}
};
BaseRepository.prototype.getById = function(id) {
return this.index.id[id].item;
};
BaseRepository.prototype.getByField = function(field, val) {
for (var i = 0, j = this.items.length; i !== j; i++) {
if (this.items[i][field] === val) {
return this.items[i];
}
}
return null;
};
BaseRepository.prototype.getAll = function() {
return this.items;
};
BaseRepository.prototype.push = function(item) {
this.index.id[item.id] = {
item: item,
index: this.items.length
}
this.items.push(item);
_super.prototype.bump.call(this);
}
BaseRepository.prototype.updateById = function(id, k, v) {
this.getById(id).update(k, v);
_super.prototype.bump.call(this);
};
return BaseRepository;
})(Versioned);
var RatRepository = (function(_super) {
__extends(RatRepository, _super);
function RatRepository(items) {
_super.call(this, items);
}
return RatRepository;
})(BaseRepository);
var ToyRepository = (function(_super) {
__extends(ToyRepository, _super);
function ToyRepository(items) {
_super.call(this, items);
}
return ToyRepository;
})(BaseRepository);
var toyRepository = new ToyRepository([
new Toy('paper'),
new Toy('ball'),
new Toy('cushion')
]);
var ratRepository = new RatRepository([
new Rat('Ivy', 'white', [toyRepository.getById(1), toyRepository.getById(2)]),
new Rat('Jinx', 'White with grey crown', [toyRepository.getById(3)])
]);
var Service = (function() {
function Service() {
this.bindings = [];
}
Service.prototype.addBinding = function(component, key) {
this.bindings.push({
component: component,
key: key
});
}
Service.prototype.updated = function() {
var props = this.GET();
_.map(this.bindings, function(binding) {
if (binding.key) {
var keyed = {};
keyed[binding.key] = props;
binding.component.setProps(keyed);
} else {
binding.component.setProps(props);
}
})
}
return Service;
})();
var RatService = (function(_super) {
__extends(RatService, _super)
function RatService(ratRepository) {
_super.call(this);
this.ratRepository = ratRepository;
}
RatService.prototype.GET = function() {
return {
__version: this.ratRepository.__version,
rats: this.ratRepository.getAll()
};
}
RatService.prototype.PUT = function(id, name, value) {
this.ratRepository.updateById(id, name, value);
_super.prototype.updated.call(this);
}
RatService.prototype.POST = function(rat) {
this.ratRepository.push(rat);
_super.prototype.updated.call(this);
}
return RatService;
})(Service);
var ratService = new RatService(ratRepository);
var VersionedMixin = {
shouldComponentUpdate : function(nextProps) {
return nextProps.__version > this.props.__version;
},
}
var RatsComponent = React.createClass({
mixins: [VersionedMixin],
// componentWillUpdate: function() {
// console.log("RAT LIST WILL UPDATE");
// },
i: 1,
handleUpdateIvy: function() {
for (var i = 0; i < 10000; i++)
ratService.PUT(1, 'name', 'IVY' + this.i++);
},
handleAddRat: function() {
var i = 0;
for (var i = 0; i < 1000; i++)
ratService.POST(new Rat('Baby rat ' + i, 'black', []));
},
render: function() {
var ratNodes = _.map(this.props.rats, function(rat) {
return <RatComponent key={'rat-' + rat.id}rat={rat} __version={rat.__version} />;
});
return (
<div>
<button onClick={this.handleUpdateIvy}>Update Ivy 10k times</button>
<button onClick={this.handleAddRat}>Add 1000 Rats</button>
<ul className="rats">
{ratNodes}
</ul>
</div>
);
}
});
var RatComponent = React.createClass({
mixins: [VersionedMixin],
// componentWillUpdate: function() {
// console.log("RAT " + this.props.rat.id + " WILL UPDATE");
// },
render: function() {
return (
<li>#{this.props.rat.id}: {this.props.rat.name} ({this.props.rat.color})</li>
);
}
});
var ratsResponse = ratService.GET();
var ratsComponent = React.renderComponent(
<RatsComponent rats={ratsResponse.rats} __version={ratsResponse.__version}/>,
document.querySelector('#main')
);
ratService.addBinding(ratsComponent);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment