Skip to content

Commit

Permalink
Merge branch 'release/0.1.14'
Browse files Browse the repository at this point in the history
  • Loading branch information
nicosommi committed Feb 19, 2016
2 parents 8ed80d1 + a0697bf commit 1b278ed
Show file tree
Hide file tree
Showing 6 changed files with 239 additions and 44 deletions.
1 change: 0 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,6 @@
"func-style": [0, "declaration"],
"generator-star": 0,
"generator-star-spacing": 0,
"global-strict": [2, "never"],
"guard-for-in": 0,
"handle-callback-err": 0,
"indent": 0,
Expand Down
65 changes: 50 additions & 15 deletions es5/lib/jsonApiModelFormatter.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ function convertModel(model) {
var attributes = model.toJSON();
var id = attributes.id;
delete attributes.id; //so it's just on the root
var relationships = [];
var relationships = {};

if (model.associations) {
var associationNames = Object.keys(model.associations);
Expand All @@ -36,18 +36,22 @@ function convertModel(model) {
var associationValue = model[associationName];
delete attributes[associationName + "Id"];
if (associationId) {
relationships.push({ type: associationType, id: associationId });
relationships[associationName] = { data: { type: associationType, id: associationId } };
} else if (associationValue) {
relationships.push({ type: associationType, id: associationValue.id });
relationships[associationName] = { data: { type: associationType, id: associationValue.id } };
}
} else if (association.type === "hasMany") {
var associationValues = model[associationName];
if (associationValues.length > 0) {
associationValues.forEach(function (associationValue) {
if (associationValue.id) {
relationships.push({ type: associationType, id: associationValue.id });
}
});
(function () {
var currentRelationship = [];
associationValues.forEach(function (associationValue) {
if (associationValue.id) {
currentRelationship.push({ type: associationType, id: associationValue.id });
}
});
relationships[associationName] = { data: currentRelationship };
})();
}
}
}
Expand All @@ -60,7 +64,7 @@ function convertModel(model) {
attributes: attributes
};

if (relationships.length > 0) {
if (Object.keys(relationships).length > 0) {
result.relationships = relationships;
}

Expand All @@ -75,13 +79,44 @@ function convertModel(model) {
}
}

function JsonApiModelFormatter(models) {
if (Array.isArray(models) || models && models.length >= 0
//HACK: this is a temporal hack to work around version issues with dovima
|| models.constructor.name === "Collection") {
return models.map(convertModel);
function parseObject(object, ModelClass) {
var newModel = new ModelClass(object.attributes);
if (object.relationships) {
Object.keys(object.relationships).forEach(function (relationshipKey) {
var relationship = object.relationships[relationshipKey];
if (relationship && relationship.data && relationship.data.id) {
var id = relationship.data.id;
newModel[relationshipKey + "Id"] = id;
}
});
}
return newModel;
}

function parse(object, ModelClass) {
if (Array.isArray(object)) {
return object.map(function (currentObject) {
return parseObject(currentObject, ModelClass);
});
} else {
return convertModel(models);
return parseObject(object, ModelClass);
}
}

function JsonApiModelFormatter() {
if (arguments.length === 1) {
var models = arguments[0];
if (Array.isArray(models) || models && models.length >= 0
//HACK: this is a temporal hack to work around version issues with dovima
|| models.constructor.name === "Collection") {
return models.map(convertModel);
} else {
return convertModel(models);
}
} else if (arguments.length === 2) {
var object = arguments[0];
var modelClass = arguments[1];
return parse(object, modelClass);
}
}

Expand Down
79 changes: 73 additions & 6 deletions es5/spec/jsonApiModelFormatter.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,15 +118,15 @@ describe("jsonApiModelFormatter", function () {
});

it("it should include the type on the relationships object", function () {
(0, _libJsonApiModelFormatterJs2["default"])(user).relationships[0].should.have.property("type");
(0, _libJsonApiModelFormatterJs2["default"])(user).relationships.posts.data[0].should.have.property("type");
});

it("it should include the right type on the relationships object", function () {
(0, _libJsonApiModelFormatterJs2["default"])(user).relationships[0].type.should.equal("post");
(0, _libJsonApiModelFormatterJs2["default"])(user).relationships.posts.data[0].type.should.equal("post");
});

it("it should include the id on the relationships object", function () {
(0, _libJsonApiModelFormatterJs2["default"])(user).relationships[0].should.have.property("id");
(0, _libJsonApiModelFormatterJs2["default"])(user).relationships.posts.data[0].should.have.property("id");
});
});

Expand All @@ -143,15 +143,15 @@ describe("jsonApiModelFormatter", function () {
});

it("it should include the type on the relationships object", function () {
(0, _libJsonApiModelFormatterJs2["default"])(user).relationships[0].should.have.property("type");
(0, _libJsonApiModelFormatterJs2["default"])(user).relationships.address.data.should.have.property("type");
});

it("it should include the right type on the relationships object", function () {
(0, _libJsonApiModelFormatterJs2["default"])(user).relationships[0].type.should.equal("address");
(0, _libJsonApiModelFormatterJs2["default"])(user).relationships.address.data.type.should.equal("address");
});

it("it should include the id on the relationships object", function () {
(0, _libJsonApiModelFormatterJs2["default"])(user).relationships[0].should.have.property("id");
(0, _libJsonApiModelFormatterJs2["default"])(user).relationships.address.data.should.have.property("id");
});
});

Expand Down Expand Up @@ -207,4 +207,71 @@ describe("jsonApiModelFormatter", function () {
(0, _libJsonApiModelFormatterJs2["default"])(apples).should.eql([]);
});
});

describe("(parsing)", function () {
var Apple = (function (_Model4) {
function Apple() {
_classCallCheck(this, Apple);

_get(Object.getPrototypeOf(Apple.prototype), "constructor", this).apply(this, arguments);
}

_inherits(Apple, _Model4);

return Apple;
})(_dovima2["default"]);

describe("(one object)", function () {
it("should return a dovima model from a json api input", function () {
var input = { type: "apples", attributes: { name: "some" } };
(0, _libJsonApiModelFormatterJs2["default"])(input, Apple).should.be.instanceOf(Apple);
});

it("should return a model with the correct attributes", function () {
var attributes = { name: "some" };
var input = { type: "apples", attributes: attributes };
(0, _libJsonApiModelFormatterJs2["default"])(input, Apple).should.be.instanceOf(Apple);
});
});

describe("(an array)", function () {
var input = undefined;
var output = undefined;
var expectedOutput = undefined;

beforeEach(function () {
input = [{ type: "apples", attributes: { name: "some" } }, { type: "apples", attributes: { name: "second" } }];
output = (0, _libJsonApiModelFormatterJs2["default"])(input, Apple);
expectedOutput = [new Apple({ name: "some" }), new Apple({ name: "second" })];
});

it("should return an array", function () {
Array.isArray(output).should.be["true"];
});

it("should return dovima models from a json api input", function () {
output[0].should.be.instanceOf(Apple);
});

it("should return the correct attributes", function () {
output.should.eql(expectedOutput);
});
});

describe("(relationships)", function () {
it("should assign the id for a relationship", function () {
var input = { type: "apples", attributes: { name: "some" }, relationships: { "tree": { data: { type: "trees", id: "4" } } } };
(0, _libJsonApiModelFormatterJs2["default"])(input, Apple).treeId.should.equal("4");
});

it("should ignore an array relationship", function () {
// support for array relationships is complex and not needed yet
// because it needs to dig into the association related in the model to find the class to instantiate
var input = { type: "apples", attributes: { name: "some" }, relationships: { "tree": { data: [{ type: "trees", id: "4" }, { type: "trees", id: "5" }] } } };
(function () {
(0, _libJsonApiModelFormatterJs2["default"])(input, Apple);
}).should.not["throw"];
});
});
});
});
66 changes: 51 additions & 15 deletions es6/lib/jsonApiModelFormatter.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Model from "dovima";
import inflect from "jargon";
import jargon from "jargon";

function convertModel(model) {
if((model && typeof (model.toJSON) === "function")
Expand All @@ -8,45 +8,47 @@ function convertModel(model) {
let attributes = model.toJSON();
const id = attributes.id;
delete attributes.id; //so it's just on the root
let relationships = [];
let relationships = {};

if(model.associations) {
const associationNames = Object.keys(model.associations);
associationNames.forEach((associationName) => {
const association = model.associations[associationName];
let associationType;
if(association) {
associationType = inflect(association.constructor.name).camel.toString();
associationType = jargon(association.constructor.name).camel.toString();
if(association.type === "hasOne") {
const associationId = model[`${associationName}Id`];
const associationValue = model[associationName];
delete attributes[`${associationName}Id`];
if(associationId) {
relationships.push({type: associationType, id: associationId});
relationships[associationName] = { data: { type: associationType, id: associationId } };
} else if (associationValue) {
relationships.push({type: associationType, id: associationValue.id});
relationships[associationName] = { data: { type: associationType, id: associationValue.id } };
}
} else if (association.type === "hasMany") {
const associationValues = model[associationName];
if(associationValues.length > 0) {
const currentRelationship = [];
associationValues.forEach((associationValue) => {
if(associationValue.id) {
relationships.push({type: associationType, id: associationValue.id});
currentRelationship.push({ type: associationType, id: associationValue.id });
}
});
relationships[associationName] = { data: currentRelationship };
}
}
}
});
}

let result = {
type: inflect(model.constructor.name).camel.toString(),
type: jargon(model.constructor.name).camel.toString(),
id: id,
attributes: attributes
};

if(relationships.length > 0) {
if(Object.keys(relationships).length > 0) {
result.relationships = relationships;
}

Expand All @@ -56,13 +58,47 @@ function convertModel(model) {
}
}

export default function JsonApiModelFormatter(models) {
if(Array.isArray(models)
|| (models && models.length >= 0)
//HACK: this is a temporal hack to work around version issues with dovima
|| (models.constructor.name === "Collection")) {
return models.map(convertModel);
function parseObject(object, ModelClass) {
const newModel = new ModelClass(object.attributes);
if(object.relationships) {
Object.keys(object.relationships).forEach(
(relationshipKey) => {
const relationship = object.relationships[relationshipKey];
if(relationship && relationship.data && relationship.data.id) {
const id = relationship.data.id;
newModel[`${relationshipKey}Id`] = id;
}
}
);
}
return newModel;
}

function parse(object, ModelClass) {
if(Array.isArray(object)) {
return object.map((currentObject) => {
return parseObject(currentObject, ModelClass);
});
} else {
return convertModel(models);
return parseObject(object, ModelClass);
}
}

export default function JsonApiModelFormatter() {
if(arguments.length === 1) {
let models = arguments[0];
if(Array.isArray(models)
|| (models && models.length >= 0)
//HACK: this is a temporal hack to work around version issues with dovima
|| (models.constructor.name === "Collection")) {
return models.map(convertModel);
} else {
return convertModel(models);
}
} else if(arguments.length === 2) {
const object = arguments[0];
const modelClass = arguments[1];
return parse(object, modelClass);
}

}

0 comments on commit 1b278ed

Please sign in to comment.