From 038e1cebe584fed3878ca499a61a01f473b1eb3d Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Tue, 4 Apr 2023 23:30:31 -0700 Subject: [PATCH] feat: full-relationship definitions when scaffolding with blueprints (#8542) * docs: show correct relationship definitions * fix tests --- packages/graph/src/-private/graph/graph.ts | 2 +- packages/model/blueprints/model/HELP.md | 4 ++-- packages/model/blueprints/model/index.js | 18 +++++------------- packages/model/src/-private/belongs-to.js | 21 +++++---------------- tests/blueprints/tests/model-test.js | 18 +++++++++--------- 5 files changed, 22 insertions(+), 41 deletions(-) diff --git a/packages/graph/src/-private/graph/graph.ts b/packages/graph/src/-private/graph/graph.ts index fe9949df10e..73dba67ab5d 100644 --- a/packages/graph/src/-private/graph/graph.ts +++ b/packages/graph/src/-private/graph/graph.ts @@ -182,7 +182,7 @@ export class Graph { export default class Post extends Model { @attr title; - @hasMany('comment') comments; + @hasMany('comment', { async: true, inverse: null }) comments; } ``` diff --git a/packages/model/blueprints/model/HELP.md b/packages/model/blueprints/model/HELP.md index 052157bed83..b4fb30443b2 100644 --- a/packages/model/blueprints/model/HELP.md +++ b/packages/model/blueprints/model/HELP.md @@ -17,8 +17,8 @@ would result in the following model: import Model, { belongsTo, hasMany, attr } from '@ember-data/model'; export default class TacoModel extends Model { - @belongsTo('protein') filling; - @hasMany('topping') toppings; + @belongsTo('protein', { async: false, inverse: null }) filling; + @hasMany('topping', { async: false, inverse: null }) toppings; @attr('string') name; @attr('number') price; @attr misc; diff --git a/packages/model/blueprints/model/index.js b/packages/model/blueprints/model/index.js index 8368d99cbd4..6fe5aba15f2 100644 --- a/packages/model/blueprints/model/index.js +++ b/packages/model/blueprints/model/index.js @@ -118,19 +118,11 @@ function nativeAttr(attr) { result; if (type === 'belongs-to') { - if (name === propertyName) { - result = '@belongsTo'; - } else { - result = "@belongsTo('" + name + "')"; - } + result = "@belongsTo('" + name + "', { async: false, inverse: null })"; } else if (type === 'has-many') { - if (inflection.pluralize(name) === propertyName) { - result = '@hasMany'; - } else { - result = "@hasMany('" + name + "')"; - } + result = "@hasMany('" + name + "', { async: false, inverse: null })"; } else if (type === '') { - result = '@attr()'; + result = '@attr'; } else { result = "@attr('" + type + "')"; } @@ -144,9 +136,9 @@ function classicAttr(attr) { result; if (type === 'belongs-to') { - result = "belongsTo('" + name + "')"; + result = "belongsTo('" + name + "', { async: false, inverse: null })"; } else if (type === 'has-many') { - result = "hasMany('" + name + "')"; + result = "hasMany('" + name + "', { async: false, inverse: null })"; } else if (type === '') { //"If you don't specify the type of the attribute, it will be whatever was provided by the server" //https://emberjs.com/guides/models/defining-models/ diff --git a/packages/model/src/-private/belongs-to.js b/packages/model/src/-private/belongs-to.js index 2e0ca6b342d..850ebeea42a 100644 --- a/packages/model/src/-private/belongs-to.js +++ b/packages/model/src/-private/belongs-to.js @@ -59,6 +59,7 @@ function normalizeType(type) { ``` #### One-To-Many + To declare a one-to-many relationship between two models, use `belongsTo` in combination with `hasMany`, like this: @@ -66,31 +67,18 @@ function normalizeType(type) { import Model, { hasMany } from '@ember-data/model'; export default class PostModel extends Model { - @hasMany('comment') comments; - } - ``` - - ```app/models/comment.js - import Model, { belongsTo } from '@ember-data/model'; - - export default class CommentModel extends Model { - @belongsTo('post') post; + @hasMany('comment', { async: false, inverse: 'post' }) comments; } ``` - You can avoid passing a string as the first parameter. In that case Ember Data - will infer the type from the key name. - ```app/models/comment.js import Model, { belongsTo } from '@ember-data/model'; export default class CommentModel extends Model { - @belongsTo post; + @belongsTo('post', { async: false, inverse: 'comments' }) post; } ``` - will lookup for a Post type. - #### Sync relationships Ember Data resolves sync relationships with the related resources @@ -102,7 +90,8 @@ function normalizeType(type) { export default class CommentModel extends Model { @belongsTo('post', { - async: false + async: false, + inverse: null }) post; } diff --git a/tests/blueprints/tests/model-test.js b/tests/blueprints/tests/model-test.js index e36ec493e38..f77816da842 100644 --- a/tests/blueprints/tests/model-test.js +++ b/tests/blueprints/tests/model-test.js @@ -75,8 +75,8 @@ describe('Acceptance: generate and destroy model blueprints', function () { expect(_file('app/models/comment.js')) .to.contain(`import Model, { belongsTo } from '@ember-data/model';`) .to.contain('export default Model.extend(') - .to.contain(" post: belongsTo('post'),") - .to.contain(" author: belongsTo('user')"); + .to.contain(" post: belongsTo('post', { async: false, inverse: null }),") + .to.contain(" author: belongsTo('user', { async: false, inverse: null })"); expect(_file('tests/unit/models/comment-test.js')).to.equal( fixture(__dirname, 'model-test/comment-default.js') @@ -91,8 +91,8 @@ describe('Acceptance: generate and destroy model blueprints', function () { expect(_file('app/models/post.js')) .to.contain(`import Model, { hasMany } from '@ember-data/model';`) .to.contain('export default Model.extend(') - .to.contain(" comments: hasMany('comment')") - .to.contain(" otherComments: hasMany('comment')"); + .to.contain(" comments: hasMany('comment', { async: false, inverse: null })") + .to.contain(" otherComments: hasMany('comment', { async: false, inverse: null })"); expect(_file('tests/unit/models/post-test.js')).to.equal(fixture(__dirname, 'model-test/post-default.js')); }); @@ -197,7 +197,7 @@ describe('Acceptance: generate and destroy model blueprints', function () { expect(_file('app/models/foo.js')) .to.contain(`import Model, { attr } from '@ember-data/model';`) .to.contain('export default class FooModel extends Model {') - .to.contain(' @attr() misc;') + .to.contain(' @attr misc;') .to.contain(" @attr('array') skills;") .to.contain(" @attr('boolean') isActive;") .to.contain(" @attr('date') birthday;") @@ -217,8 +217,8 @@ describe('Acceptance: generate and destroy model blueprints', function () { expect(_file('app/models/comment.js')) .to.contain(`import Model, { belongsTo } from '@ember-data/model';`) .to.contain('export default class CommentModel extends Model {') - .to.contain(' @belongsTo post;') - .to.contain(" @belongsTo('user') author;"); + .to.contain(` @belongsTo('post', { async: false, inverse: null }) post;`) + .to.contain(" @belongsTo('user', { async: false, inverse: null }) author;"); expect(_file('tests/unit/models/comment-test.js')).to.equal( fixture(__dirname, 'model-test/comment-default.js') @@ -233,8 +233,8 @@ describe('Acceptance: generate and destroy model blueprints', function () { expect(_file('app/models/post.js')) .to.contain(`import Model, { hasMany } from '@ember-data/model';`) .to.contain('export default class PostModel extends Model {') - .to.contain(' @hasMany comments;') - .to.contain(" @hasMany('comment') otherComments;"); + .to.contain(` @hasMany('comment', { async: false, inverse: null }) comments;`) + .to.contain(" @hasMany('comment', { async: false, inverse: null }) otherComments;"); expect(_file('tests/unit/models/post-test.js')).to.equal(fixture(__dirname, 'model-test/post-default.js')); });