Skip to content

Commit

Permalink
add relationships
Browse files Browse the repository at this point in the history
  • Loading branch information
nicosommi committed Dec 4, 2015
1 parent a9bf5f6 commit 1f6fb42
Show file tree
Hide file tree
Showing 4 changed files with 272 additions and 10 deletions.
61 changes: 53 additions & 8 deletions es5/lib/jsonApiModelFormatter.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,59 @@ var _jargon2 = _interopRequireDefault(_jargon);

function convertModel(model) {
if (model && typeof model.toJSON === "function" || model instanceof _dovima2["default"]) {
var attributes = model.toJSON();
var id = attributes.id;
delete attributes.id; //so it's just on the root
return {
type: (0, _jargon2["default"])(model.constructor.name).camel.toString(),
id: id,
attributes: attributes
};
var _ret = (function () {

var attributes = model.toJSON();
var id = attributes.id;
delete attributes.id; //so it's just on the root
var relationships = [];

if (model.associations) {
var associationNames = Object.keys(model.associations);
associationNames.forEach(function (associationName) {
var association = model.associations[associationName];
var associationType = undefined;
if (association) {
associationType = (0, _jargon2["default"])(association.constructor.name).camel.toString();
if (association.type === "hasOne") {
var associationId = model[associationName + "Id"];
var associationValue = model[associationName];
delete attributes[associationName + "Id"];
if (associationId) {
relationships.push({ type: associationType, id: associationId });
} else if (associationValue) {
relationships.push({ 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 });
}
});
}
}
}
});
}

var result = {
type: (0, _jargon2["default"])(model.constructor.name).camel.toString(),
id: id,
attributes: attributes
};

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

return {
v: result
};
})();

if (typeof _ret === "object") return _ret.v;
} else {
throw new Error("The object provided to be formatted as json is not a dovima Model / Collection.");
}
Expand Down
102 changes: 102 additions & 0 deletions es5/spec/jsonApiModelFormatter.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,48 @@ describe("jsonApiModelFormatter", function () {

_inherits(User, _Model);

_createClass(User, [{
key: "associate",
value: function associate() {
this.hasMany("posts", Post);
this.hasOne("address", Address);
}
}]);

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

var Address = (function (_Model2) {
function Address() {
_classCallCheck(this, Address);

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

_inherits(Address, _Model2);

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

var Post = (function (_Model3) {
function Post() {
_classCallCheck(this, Post);

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

_inherits(Post, _Model3);

_createClass(Post, [{
key: "associate",
value: function associate() {
this.belongsTo("user", User);
}
}]);

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

var user = undefined,
userAttributes = undefined;

Expand Down Expand Up @@ -65,6 +104,69 @@ describe("jsonApiModelFormatter", function () {
}).should["throw"]("The object provided to be formatted as json is not a dovima Model / Collection.");
});

describe("(relationships)", function () {
var post = undefined;

describe("(hasMany)", function () {
beforeEach(function () {
post = new Post({ "id": 23 });
user.posts.push(post);
});

it("it should include a relationships object", function () {
(0, _libJsonApiModelFormatterJs2["default"])(user).should.have.property("relationships");
});

it("it should include the type on the relationships object", function () {
(0, _libJsonApiModelFormatterJs2["default"])(user).relationships[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");
});

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

describe("(hasOne)", function () {
var address = undefined;

beforeEach(function () {
address = new Address();
user.address = address;
});

it("it should include a relationships object", function () {
(0, _libJsonApiModelFormatterJs2["default"])(user).should.have.property("relationships");
});

it("it should include the type on the relationships object", function () {
(0, _libJsonApiModelFormatterJs2["default"])(user).relationships[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("address");
});

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

describe("(belongsTo)", function () {
beforeEach(function () {
post = new Post({ "id": 23 });
post.user = user;
});

it("it should not have a relationships object", function () {
(0, _libJsonApiModelFormatterJs2["default"])(post).should.not.have.property("relationships");
});
});
});

describe("function object conflicts", function () {
it("should work correctly if the object has a toJSON function", function () {
var result = "some result";
Expand Down
41 changes: 40 additions & 1 deletion es6/lib/jsonApiModelFormatter.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,53 @@ import inflect from "jargon";
function convertModel(model) {
if((model && typeof (model.toJSON) === "function")
|| model instanceof Model) {

let attributes = model.toJSON();
const id = attributes.id;
delete attributes.id; //so it's just on the root
return {
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();
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});
} else if (associationValue) {
relationships.push({type: associationType, id: associationValue.id});
}
} else if (association.type === "hasMany") {
const associationValues = model[associationName];
if(associationValues.length > 0) {
associationValues.forEach((associationValue) => {
if(associationValue.id) {
relationships.push({type: associationType, id: associationValue.id});
}
});
}
}
}
});
}

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

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

return result;
} else {
throw new Error(`The object provided to be formatted as json is not a dovima Model / Collection.`);
}
Expand Down
78 changes: 77 additions & 1 deletion es6/spec/jsonApiModelFormatter.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,20 @@ import jsonApiModelFormatter from "../lib/jsonApiModelFormatter.js";
import Model from "dovima";

describe("jsonApiModelFormatter", () => {
class User extends Model {}
class User extends Model {
associate() {
this.hasMany("posts", Post);
this.hasOne("address", Address);
}
}

class Address extends Model {}

class Post extends Model {
associate() {
this.belongsTo("user", User);
}
}

let user,
userAttributes;
Expand Down Expand Up @@ -38,6 +51,69 @@ describe("jsonApiModelFormatter", () => {
}.should.throw("The object provided to be formatted as json is not a dovima Model / Collection.");
});

describe("(relationships)", () => {
let post;

describe("(hasMany)", () => {
beforeEach(() => {
post = new Post({"id": 23});
user.posts.push(post);
});

it("it should include a relationships object", () => {
jsonApiModelFormatter(user).should.have.property("relationships");
});

it("it should include the type on the relationships object", () => {
jsonApiModelFormatter(user).relationships[0].should.have.property("type");
});

it("it should include the right type on the relationships object", () => {
jsonApiModelFormatter(user).relationships[0].type.should.equal("post");
});

it("it should include the id on the relationships object", () => {
jsonApiModelFormatter(user).relationships[0].should.have.property("id");
});
});

describe("(hasOne)", () => {
let address;

beforeEach(() => {
address = new Address();
user.address = address;
});

it("it should include a relationships object", () => {
jsonApiModelFormatter(user).should.have.property("relationships");
});

it("it should include the type on the relationships object", () => {
jsonApiModelFormatter(user).relationships[0].should.have.property("type");
});

it("it should include the right type on the relationships object", () => {
jsonApiModelFormatter(user).relationships[0].type.should.equal("address");
});

it("it should include the id on the relationships object", () => {
jsonApiModelFormatter(user).relationships[0].should.have.property("id");
});
});

describe("(belongsTo)", () => {
beforeEach(() => {
post = new Post({"id": 23});
post.user = user;
});

it("it should not have a relationships object", () => {
jsonApiModelFormatter(post).should.not.have.property("relationships");
});
});
});

describe("function object conflicts", () => {
it("should work correctly if the object has a toJSON function", () => {
const result = "some result";
Expand Down

0 comments on commit 1f6fb42

Please sign in to comment.