Skip to content
This repository was archived by the owner on Jan 22, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions addon/mixins/resource-operations.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,9 @@ export default Ember.Mixin.create({
updateRelationship(relationship, ids, errorCallback) {
let related = this.get(relationship);
let rollback;
if (related.kind === 'hasOne') {
if (related.kind === 'toOne') {
rollback = related.get('id');
} else if (related.kind === 'hasMany') {
} else if (related.kind === 'toMany') {
rollback = related.mapBy('id');
}
this._updateRelationshipsData(relationship, ids);
Expand Down
42 changes: 21 additions & 21 deletions addon/models/resource.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
import Ember from 'ember';
import { pluralize, singularize } from 'ember-inflector';
import attr from 'ember-jsonapi-resources/utils/attr';
import hasOne from 'ember-jsonapi-resources/utils/has-one';
import hasMany from 'ember-jsonapi-resources/utils/has-many';
import { toOne, hasOne } from 'ember-jsonapi-resources/utils/to-one';
import { toMany, hasMany } from 'ember-jsonapi-resources/utils/to-many';
import { isType } from 'ember-jsonapi-resources/utils/is';
import ResourceOperationsMixin from '../mixins/resource-operations';

Expand Down Expand Up @@ -187,9 +187,9 @@ const Resource = Ember.Object.extend(ResourceOperationsMixin, {

Also sets or adds to the `content` of the related proxy object.

- For has-many relations the related identifier object is added to
- For to-many relations the related identifier object is added to
the resource linkage data array.
- For has-one relations the resource identifier object is assigned,
- For to-one relations the resource identifier object is assigned,
so the relation may be replaced.

See:
Expand Down Expand Up @@ -248,12 +248,12 @@ const Resource = Ember.Object.extend(ResourceOperationsMixin, {
setupRelationshipTracking.call(this, relation, meta.kind);
let ref = this._relationships[relation];
let relationshipData = this.get(`relationships.${relation}.data`);
if (meta && meta.kind === 'hasOne') {
if (meta && meta.kind === 'toOne') {
if (!relationshipData || relationshipData.id !== identifier.id) {
ref.changed = identifier;
ref.previous = ref.previous || previous;
}
} else if (meta && meta.kind === 'hasMany') {
} else if (meta && meta.kind === 'toMany') {
let id = identifier.id;
ref.removals = Ember.A(ref.removals.rejectBy('id', id));
if (!ref.added.findBy('id', id)) {
Expand All @@ -266,8 +266,8 @@ const Resource = Ember.Object.extend(ResourceOperationsMixin, {
Removes resource identifier object of the relationship data. Also, sets the
`content` of the related (computed property's) proxy object to `null`.

- For has-one relations the (resource linkage) data is set to `null`.
- For has-many relations the resource identifier object is removed from
- For to-one relations the (resource linkage) data is set to `null`.
- For to-many relations the resource identifier object is removed from
the resource Linkage `data` array.

See:
Expand Down Expand Up @@ -315,10 +315,10 @@ const Resource = Ember.Object.extend(ResourceOperationsMixin, {
let ref = this._relationships[relation] = this._relationships[relation] || {};
let meta = this.relationMetadata(relation);
setupRelationshipTracking.call(this, relation, meta.kind);
if (meta.kind === 'hasOne') {
if (meta.kind === 'toOne') {
ref.changed = null;
ref.previous = ref.previous || this.get('relationships.' + relation).data;
} else if (meta.kind === 'hasMany') {
} else if (meta.kind === 'toMany') {
ref.added = Ember.A(ref.added.rejectBy('id', id));
if (!ref.removals.findBy('id', id)) {
ref.removals.pushObject({ type: pluralize(relation), id: id });
Expand Down Expand Up @@ -428,11 +428,11 @@ const Resource = Ember.Object.extend(ResourceOperationsMixin, {
relations.forEach((relation) => {
let ref = this._relationships[relation];
let meta = this.relationMetadata(relation);
if (meta && meta.kind === 'hasOne') {
if (meta && meta.kind === 'toOne') {
if (ref.changed && ref.changed.id && ref.previous && ref.previous.id) {
this.addRelationship(relation, ref.previous.id);
}
} else if (meta && meta.kind === 'hasMany') {
} else if (meta && meta.kind === 'toMany') {
let added = ref.added.mapBy('id');
let removed = ref.removals.mapBy('id');
added.forEach( (id) => {
Expand Down Expand Up @@ -499,11 +499,11 @@ const Resource = Ember.Object.extend(ResourceOperationsMixin, {

/**
Sets the relationships data, used after the promise proxy resolves by
hasOne and hasMany helpers
toOne and toMany helpers

@method didResolveProxyRelation
@param {String} relation name
@param {String} kind of relation hasOne or hasMany
@param {String} kind of relation toOne or toMany
@param {Array|Object} related resource(s)
*/
didResolveProxyRelation(relation, kind, related) {
Expand All @@ -518,9 +518,9 @@ const Resource = Ember.Object.extend(ResourceOperationsMixin, {
let relationshipData = 'relationships.' + relation + '.data';
let data = this.get(relationshipData);
if (!data) {
if (kind === 'hasOne') {
if (kind === 'toOne') {
this.set(relationshipData, {});
} else if (kind === 'hasMany') {
} else if (kind === 'toMany') {
this.set(relationshipData, Ember.A([]));
}
}
Expand Down Expand Up @@ -620,7 +620,7 @@ Resource.reopenClass({

export default Resource;

export { attr, hasOne, hasMany };
export { attr, toOne, toMany, hasOne, hasMany };

let _rp = 'service type id attributes relationships links meta _attributes isNew cacheDuration isCacheExpired';
const ignoredMetaProps = _rp.split(' ');
Expand Down Expand Up @@ -650,9 +650,9 @@ function setupRelationship(relation, kind) {
ref.links = {};
}
if (!ref.data) {
if (kind === 'hasOne') {
if (kind === 'toOne') {
ref.data = null;
} else if (kind === 'hasMany') {
} else if (kind === 'toMany') {
ref.data = Ember.A([]);
}
}
Expand All @@ -661,10 +661,10 @@ function setupRelationship(relation, kind) {
function setupRelationshipTracking(relation, kind) {
this._relationships[relation] = this._relationships[relation] || {};
let ref = this._relationships[relation];
if (kind === 'hasOne') {
if (kind === 'toOne') {
ref.changed = ref.changed || null;
ref.previous = ref.previous || null;
} else if (kind === 'hasMany') {
} else if (kind === 'toMany') {
ref.added = ref.added || Ember.A([]);
ref.removals = ref.removals || Ember.A([]);
}
Expand Down
2 changes: 1 addition & 1 deletion addon/utils/attr.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { isBlank, isDasherized, isType } from 'ember-jsonapi-resources/utils/is'
```js
import Ember from 'ember';
import Resource from 'ember-jsonapi-resources/models/resource';
import { attr, hasOne, hasMany } from 'ember-jsonapi-resources/models/resource';
import { attr, toOne, toMany } from 'ember-jsonapi-resources/models/resource';

export default Resource.extend({
type: 'articles',
Expand Down
10 changes: 5 additions & 5 deletions addon/utils/related-proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,15 @@ const RelatedProxyUtil = Ember.Object.extend({

@method createProxy
@param {Resource} resource
@param {String} kind 'hasMany' or 'hasOne'
@param {String} kind 'toMany' or 'toOne'
@return {PromiseProxy|ObjectProxy|ArrayProxy} proxy instance, new resource uses mock relations
*/
createProxy(resource, kind) {
let proxyFactory, newContent;
if (kind === 'hasMany') {
if (kind === 'toMany') {
proxyFactory = Ember.ArrayProxy;
newContent = Ember.A([]);
} else if (kind === 'hasOne') {
} else if (kind === 'toOne') {
proxyFactory = Ember.ObjectProxy;
newContent = Ember.Object.create();
}
Expand All @@ -76,7 +76,7 @@ const RelatedProxyUtil = Ember.Object.extend({
/**
@method proxySetup
@param {Resource} resource
@param {String} kind 'hasMany' or 'hasOne'
@param {String} kind 'toMany' or 'toOne'
@param {Ember.ObjectProxy|Ember.ArrayProxy} proxyFactory
@return {PromiseProxy} proxy
*/
Expand All @@ -92,7 +92,7 @@ const RelatedProxyUtil = Ember.Object.extend({
'promise': promise, 'type': relation, 'kind': kind
});
return proxyProto.create({
content: (kind === 'hasOne') ? Ember.Object.create() : Ember.A([])
content: (kind === 'toOne') ? Ember.Object.create() : Ember.A([])
});
},

Expand Down
18 changes: 10 additions & 8 deletions addon/utils/has-many.js → addon/utils/to-many.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
@module ember-jsonapi-resources
@submodule utils
@main hasMany
@main toMany
**/

import Ember from 'ember';
Expand All @@ -16,7 +16,7 @@ import { isDasherized } from 'ember-jsonapi-resources/utils/is';
let Author = Resource.extend({
type: 'authors',
name: attr(),
posts: hasMany('posts')
posts: toMany('posts')
});
```

Expand All @@ -30,34 +30,36 @@ import { isDasherized } from 'ember-jsonapi-resources/utils/is';

let Supervisor = Person.extend({
type: 'supervisors',
directReports: hasMany({ resource: 'employees', type: 'people' })
directReports: toMany({ resource: 'employees', type: 'people' })
});
```

@method hasMany
@method toMany
@for Resource
@final
@param {String|Object} relation the name of the relationship
@param {String} relation.resource the name of the relationship
@param {String} relation.type the name of the type or service to use
@return {Object} computed property
*/
export default function hasMany(relation) {
export function toMany(relation) {
let type = relation;
if (typeof type === 'object') {
assertResourceAndTypeProps(relation);
type = relation.type;
relation = relation.resource;
}
assertDasherizedHasManyRelation(relation);
let kind = 'hasMany';
let kind = 'toMany';
let util = RelatedProxyUtil.create({'relationship': relation, 'type': type, kind: kind});
let path = linksPath(relation);
return Ember.computed(path, function () {
return util.createProxy(this, kind);
}).meta({relation: relation, type: type, kind: kind});
}

export let hasMany = toMany;

function assertResourceAndTypeProps(relation) {
try {
let msg = 'Options must include properties: resource, type';
Expand All @@ -70,8 +72,8 @@ function assertResourceAndTypeProps(relation) {
function assertDasherizedHasManyRelation(name) {
try {
let relationName = Ember.String.dasherize(name);
let msg = " are recommended to use dasherized names, e.g `hasMany('"+ relationName +"')`";
msg += ", instead of `hasMany('"+ name +"')`";
let msg = " are recommended to use dasherized names, e.g `toMany('"+ relationName +"')`";
msg += ", instead of `toMany('"+ name +"')`";
Ember.assert(msg, isDasherized(name));
} catch(e) {
Ember.Logger.warn(e.message);
Expand Down
18 changes: 10 additions & 8 deletions addon/utils/has-one.js → addon/utils/to-one.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
@module ember-jsonapi-resources
@submodule utils
@main hasOne
@main toOne
**/

import Ember from 'ember';
Expand All @@ -15,7 +15,7 @@ import { isDasherized } from 'ember-jsonapi-resources/utils/is';
```js
let Employee = Person.extend({
type: 'employees',
supervisor: hasOne('supervisor')
supervisor: toOne('supervisor')
});
```

Expand All @@ -29,34 +29,36 @@ import { isDasherized } from 'ember-jsonapi-resources/utils/is';

let Employee = Person.extend({
type: 'employees',
supervisor: hasOne({ resource: 'supervisor', type: 'people' })
supervisor: toOne({ resource: 'supervisor', type: 'people' })
});
```

@method hasOne
@method toOne
@for Resource
@final
@param {String|Object} relation the name of the relationship
@param {String} relation.resource the name of the relationship
@param {String} relation.type the name of the type or service to use
@return {Object} computed property
*/
export default function hasOne(relation) {
export function toOne(relation) {
let type = relation;
if (typeof type === 'object') {
assertResourceAndTypeProps(relation);
type = relation.type;
relation = relation.resource;
}
assertDasherizedHasOneRelation(type);
let kind = 'hasOne';
let kind = 'toOne';
let util = RelatedProxyUtil.create({relationship: relation, type: type, kind: kind});
let path = linksPath(relation);
return Ember.computed(path, function () {
return util.createProxy(this, kind);
}).meta({relation: relation, type: type, kind: kind});
}

export let hasOne = toOne;

function assertResourceAndTypeProps(relation) {
try {
let msg = 'Options must include properties: resource, type';
Expand All @@ -69,8 +71,8 @@ function assertResourceAndTypeProps(relation) {
function assertDasherizedHasOneRelation(name) {
try {
let relationName = Ember.String.dasherize(name);
let msg = " are recommended to use dasherized names, e.g `hasOne('"+ relationName +"')`";
msg += ", instead of `hasOne('"+ name +"')`";
let msg = " are recommended to use dasherized names, e.g `toOne('"+ relationName +"')`";
msg += ", instead of `toOne('"+ name +"')`";
Ember.assert(msg, isDasherized(name));
} catch(e) {
Ember.Logger.warn(e.message);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Ember from 'ember';
import Resource from 'ember-jsonapi-resources/models/resource';
import { attr, hasOne, hasMany } from 'ember-jsonapi-resources/models/resource';
import { attr, toOne, toMany } from 'ember-jsonapi-resources/models/resource';

let <%= classifiedModuleName %>Model = Resource.extend({
type: '<%= resource %>',
Expand Down
8 changes: 4 additions & 4 deletions blueprints/jsonapi-model/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,10 @@ module.exports = {

function resourceAttr(name, type) {
switch (type) {
case 'has-one':
return 'hasOne(\'' + name + '\')';
case 'has-many':
return 'hasMany(\'' + name + '\')';
case 'to-one':
return 'toOne(\'' + name + '\')';
case 'to-many':
return 'toMany(\'' + name + '\')';
case '':
return 'attr()';
default:
Expand Down
4 changes: 2 additions & 2 deletions tests/dummy/app/models/author.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Ember from 'ember';
import Resource from './resource';
import { attr, hasMany } from 'ember-jsonapi-resources/models/resource';
import { attr, toMany } from 'ember-jsonapi-resources/models/resource';

export default Resource.extend({
type: 'authors',
Expand All @@ -9,5 +9,5 @@ export default Resource.extend({
name: attr('string'),
email: attr('string'),

posts: hasMany('posts')
posts: toMany('posts')
});
6 changes: 3 additions & 3 deletions tests/dummy/app/models/comment.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Ember from 'ember';
import Resource from './resource';
import { attr, hasOne } from 'ember-jsonapi-resources/models/resource';
import { attr, toOne } from 'ember-jsonapi-resources/models/resource';

export default Resource.extend({
type: 'comments',
Expand All @@ -14,6 +14,6 @@ export default Resource.extend({
}
}),

commenter: hasOne('commenter'),
post: hasOne('post')
commenter: toOne('commenter'),
post: toOne('post')
});
Loading