Skip to content

Instantly share code, notes, and snippets.

@borissuska
Last active June 29, 2017 14:03
Show Gist options
  • Save borissuska/635e666091bf3356b40d7744fac2aa5c to your computer and use it in GitHub Desktop.
Save borissuska/635e666091bf3356b40d7744fac2aa5c to your computer and use it in GitHub Desktop.
Changeset test
import Adapter from "ember-data/adapters/json-api";
export default Adapter.extend();
import Ember from 'ember';
import Changeset from 'ember-changeset';
import lookupValidator from 'ember-changeset-validations';
import {
validatePresence
} from 'ember-changeset-validations/validators';
export default Ember.Controller.extend({
store: Ember.inject.service(),
appName: 'Ember Twiddle',
model: undefined,
changeset: undefined,
actions: {
loadModel() {
this.get('store').findRecord('myModel', 1).then((model) => this.set('model', model));
},
editModel() {
let validations = {
name: validatePresence(true)
};
let ch = new Changeset(this.get('model'), lookupValidator(validations), validations);
this.set('changeset', ch);
},
updateModelRandomly() {
Ember.$.get('/my-models/1/random-update');
},
submit() {
let changeset = this.get('changeset');
changeset.validate().then(() => {
if (changeset.get('isValid')) {
changeset.save().then((model) => {
this.set('changeset', undefined);
}).catch((e) => {
let errors = this.get('model.errors');
console.log(errors);
errors.forEach(error => {
console.log(error.attribute, error.message);
let key = error.attribute;
let validation = error.message;
changeset.addError(key, { validation });
});
});
}
});
},
rollback() {
this.get('changeset').rollback();
this.set('changeset', undefined);
}
}
});
export function returnJSON(status, body) {
return json(...arguments);
};
export function json(status, body) {
if (arguments.length === 1) {
body = status;
status = 200;
}
return [
status,
{ "Content-Type": "application/json" },
JSON.stringify(body)
];
};
export const server = new Pretender();
export function initialize() {
server.handledRequest = function(verb, path, request) {
console.log(`handled request to ${verb} ${path}`);
};
server.unhandledRequest = function(verb, path, request) {
console.log(`undhandled request ${verb} ${path}`);
};
let db = {
1: {
name: 'test',
version: 1
}
};
server.map(function() {
// Get latest version of my model
this.get('/my-models/:id', function(request) {
return json({
data: {
type: 'my-model',
id: request.params.id,
attributes: db[request.params.id]
}
});
});
// Randomly update my model - it simulates concurrent update
this.get('/my-models/:id/random-update', function(request) {
db[request.params.id].name += '-' + Math.round(Math.random()*10000);
db[request.params.id].version++;
return json({status: 'ok'});
});
// update my model only if version matches
this.patch('/my-models/:id', function(request) {
let originalData = db[request.params.id];
let newData = JSON.parse(request.requestBody).data.attributes;
if (originalData.version === newData.version) {
newData.version++;
db[request.params.id] = newData;
return json(202, {
data: {
type: 'my-model',
id: request.params.id,
attributes: newData
}
});
} else {
return json(409, {
data: {
type: 'my-model',
id: request.params.id,
attributes: newData
},
errors: [{
code: 409,
id: "328a653a-810c-4da9-ab68-23844ca72847",
status: "409",
title: "Concurrent modification of entity",
source: {
pointer: "data/attributes/version"
}
}]
});
}
});
});
};
export default {
name: 'pretender',
initialize
};
import Model from "ember-data/model";
import attr from "ember-data/attr";
import { belongsTo, hasMany } from "ember-data/relationships";
export default Model.extend({
name: attr('string'),
version: attr('number')
});
import Serializer from "ember-data/serializers/json-api";
export default Serializer.extend();
<h1>changeset concurrent modification example</h1>
<p>
Demonstrates how to handle edit if model has been chnaged concurrently.
<ol>
<li>Load model by clicking on "Load model" button</li>
<li>Change model, edit model's name</li>
<li>Simulate cuncurrent modification of the model by clicking on "Update model randomly" button</li>
<li>Save your model, it is rejected by server because mismatchs versions</li>
</ol>
</p>
Name: {{model.name}}<br>
Version: {{model.version}}<br>
{{#if model.hasDirtyAttributes}}
Model is DIRTY
{{else}}
Model is clean
{{/if}}
<br>
{{#if changeset}}
<br>
<form>
Name: {{input value=changeset.name}}<br>
Version: {{changeset.version}}<br>
{{#if changeset.isInvalid}}
Invalid data.<br>
<ul>
{{#each changeset.errors as |error|}}
<li>{{error.key}}: {{error.validation}}</li>
{{/each}}
</ul>
{{/if}}
<br>
<button {{action "submit"}}>Submit</button>
<button {{action "rollback"}}>Rollback</button>
</form>
<br>
{{/if}}
<br>
<button {{action "loadModel"}}>Load model</button>
<button {{action "editModel"}}>Edit model</button>
<br>
<br>
<button {{action "updateModelRandomly"}}>Update model randomly</button>
{
"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",
"route-recognizer": "https://rawgit.com/tildeio/route-recognizer/56f5fcec6ae58d8e86b5dc77609809fb91198142/dist/route-recognizer.js",
"FakeXMLHttpRequest": "https://rawgit.com/pretenderjs/FakeXMLHttpRequest/23c3a96b5b24f1bfe595867437e4f128a29c2840/fake_xml_http_request.js",
"pretender": "https://rawgit.com/pretenderjs/pretender/c6de9afe18b1472aded2592f5a80ad9a26a0e262/pretender.js"
},
"addons": {
"ember-data": "2.12.1",
"ember-changeset": "*",
"ember-changeset-validations": "*"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment