Javascript 余烬-未更新多对多关系数据

Javascript 余烬-未更新多对多关系数据,javascript,ember.js,many-to-many,ember-data,Javascript,Ember.js,Many To Many,Ember Data,我有一个扬声器模型,如下所示: import attr from 'ember-data/attr'; import ModelBase from 'open-event-frontend/models/base'; import { belongsTo, hasMany } from 'ember-data/relationships'; export default ModelBase.extend({ /** * Attributes */ name

我有一个扬声器模型,如下所示:

import attr from 'ember-data/attr';
import ModelBase from 'open-event-frontend/models/base';
import { belongsTo, hasMany } from 'ember-data/relationships';

export default ModelBase.extend({

  /**
   * Attributes
   */

  name               : attr('string'),
  email              : attr('string'),
  photoUrl           : attr('string'),
  thumbnailImageUrl  : attr('string'),
  shortBiography     : attr('string'),
  longBiography      : attr('string'),
  speakingExperience : attr('string'),
  mobile             : attr('string'),
  location           : attr('string'),
  website            : attr('string'),
  twitter            : attr('string'),
  facebook           : attr('string'),
  github             : attr('string'),
  linkedin           : attr('string'),
  organisation       : attr('string'),
  isFeatured         : attr('boolean', { default: false }),
  position           : attr('string'),
  country            : attr('string'),
  city               : attr('string'),
  gender             : attr('string'),
  heardFrom          : attr('string'),

  /**
   * Relationships
   */

  user     : belongsTo('user'),
  event    : belongsTo('event'),
  sessions : hasMany('session')

});
import attr from 'ember-data/attr';
import moment from 'moment';
import ModelBase from 'open-event-frontend/models/base';
import { belongsTo, hasMany } from 'ember-data/relationships';
import { computedDateTimeSplit } from 'open-event-frontend/utils/computed-helpers';

const detectedTimezone = moment.tz.guess();

export default ModelBase.extend({
  title         : attr('string'),
  subtitle      : attr('string'),
  startsAt      : attr('moment', { defaultValue: () => moment.tz(detectedTimezone).add(1, 'months').startOf('day') }),
  endsAt        : attr('moment', { defaultValue: () => moment.tz(detectedTimezone).add(1, 'months').hour(17).minute(0) }),
  shortAbstract : attr('string'),
  longAbstract  : attr('string'),
  language      : attr('string'),
  level         : attr('string'),
  comments      : attr('string'),
  state         : attr('string'),
  slidesUrl     : attr('string'),
  videoUrl      : attr('string'),
  audioUrl      : attr('string'),
  signupUrl     : attr('string'),
  sendEmail     : attr('boolean'),

  isMailSent: attr('boolean', { defaultValue: false }),

  createdAt      : attr('string'),
  deletedAt      : attr('string'),
  submittedAt    : attr('string', { defaultValue: () => moment() }),
  lastModifiedAt : attr('string'),
  sessionType    : belongsTo('session-type'),
  microlocation  : belongsTo('microlocation'),
  track          : belongsTo('track'),
  speakers       : hasMany('speaker'),
  event          : belongsTo('event'), // temporary
  creator        : belongsTo('user'),

  startAtDate : computedDateTimeSplit.bind(this)('startsAt', 'date'),
  startAtTime : computedDateTimeSplit.bind(this)('startsAt', 'time'),
  endsAtDate  : computedDateTimeSplit.bind(this)('endsAt', 'date'),
  endsAtTime  : computedDateTimeSplit.bind(this)('endsAt', 'time')
});
以及会话的模型,如下所示:

import attr from 'ember-data/attr';
import ModelBase from 'open-event-frontend/models/base';
import { belongsTo, hasMany } from 'ember-data/relationships';

export default ModelBase.extend({

  /**
   * Attributes
   */

  name               : attr('string'),
  email              : attr('string'),
  photoUrl           : attr('string'),
  thumbnailImageUrl  : attr('string'),
  shortBiography     : attr('string'),
  longBiography      : attr('string'),
  speakingExperience : attr('string'),
  mobile             : attr('string'),
  location           : attr('string'),
  website            : attr('string'),
  twitter            : attr('string'),
  facebook           : attr('string'),
  github             : attr('string'),
  linkedin           : attr('string'),
  organisation       : attr('string'),
  isFeatured         : attr('boolean', { default: false }),
  position           : attr('string'),
  country            : attr('string'),
  city               : attr('string'),
  gender             : attr('string'),
  heardFrom          : attr('string'),

  /**
   * Relationships
   */

  user     : belongsTo('user'),
  event    : belongsTo('event'),
  sessions : hasMany('session')

});
import attr from 'ember-data/attr';
import moment from 'moment';
import ModelBase from 'open-event-frontend/models/base';
import { belongsTo, hasMany } from 'ember-data/relationships';
import { computedDateTimeSplit } from 'open-event-frontend/utils/computed-helpers';

const detectedTimezone = moment.tz.guess();

export default ModelBase.extend({
  title         : attr('string'),
  subtitle      : attr('string'),
  startsAt      : attr('moment', { defaultValue: () => moment.tz(detectedTimezone).add(1, 'months').startOf('day') }),
  endsAt        : attr('moment', { defaultValue: () => moment.tz(detectedTimezone).add(1, 'months').hour(17).minute(0) }),
  shortAbstract : attr('string'),
  longAbstract  : attr('string'),
  language      : attr('string'),
  level         : attr('string'),
  comments      : attr('string'),
  state         : attr('string'),
  slidesUrl     : attr('string'),
  videoUrl      : attr('string'),
  audioUrl      : attr('string'),
  signupUrl     : attr('string'),
  sendEmail     : attr('boolean'),

  isMailSent: attr('boolean', { defaultValue: false }),

  createdAt      : attr('string'),
  deletedAt      : attr('string'),
  submittedAt    : attr('string', { defaultValue: () => moment() }),
  lastModifiedAt : attr('string'),
  sessionType    : belongsTo('session-type'),
  microlocation  : belongsTo('microlocation'),
  track          : belongsTo('track'),
  speakers       : hasMany('speaker'),
  event          : belongsTo('event'), // temporary
  creator        : belongsTo('user'),

  startAtDate : computedDateTimeSplit.bind(this)('startsAt', 'date'),
  startAtTime : computedDateTimeSplit.bind(this)('startsAt', 'time'),
  endsAtDate  : computedDateTimeSplit.bind(this)('endsAt', 'date'),
  endsAtTime  : computedDateTimeSplit.bind(this)('endsAt', 'time')
});
很明显,会话和演讲者有一种多对多的关系。因此,我将会话添加到演讲者,然后保存它们。这两个记录都已在服务器上成功创建,但未建立链接。我已经用postman测试了服务器端点,它工作得很好。所以,我想我错过了一些东西

这是控制器代码:

import Controller from '@ember/controller';
export default Controller.extend({
  actions: {
    save() {
      this.set('isLoading', true);
      this.get('model.speaker.sessions').pushObject(this.get('model.session'));

      this.get('model.session').save()
        .then(() => {
          this.get('model.speaker').save()
            .then(() => {
              this.get('notify').success(this.get('l10n').t('Your session has been saved'));
              this.transitionToRoute('events.view.sessions', this.get('model.event.id'));
            })
            .catch(() => {
              this.get('notify').error(this.get('l10n').t('Oops something went wrong. Please try again'));
            });
        })
        .catch(() => {
          this.get('notify').error(this.get('l10n').t('Oops something went wrong. Please try again'));
        })
        .finally(() => {
          this.set('isLoading', false);
        });
    }
  }
});

正如@Lux在评论中提到的,默认情况下,余烬数据不序列化在所有情况下都有许多关系。这适用于所有扩展而不是重写方法的序列化程序。这是和的情况

用于确定是否应序列化多个关系的逻辑非常复杂,而且没有很好的文档记录。因此,需要了解细节

通常,只有当且仅当满足以下条件时,才会序列化具有多个关系:

如果序列化程序配置强制执行。要将序列化程序配置为强制序列化特定关系,必须包含一个关系名为的键,该键包含一个对象{serialize:true}

如果序列化程序的attrs配置未禁止。它与1相反。attrs选项包含一个关系名为的键,该键包含一个对象{serialize:false}

如果是多对无关系,则表示没有反向关系

如果是多对多的关系

根据您的问题,多对多关系没有序列化。可能有很多因素导致您的问题,但我敢打赌是这个:

若我没弄错的话,多对多关系的两个记录还并没有在服务器上持久化。我假设您不在客户端生成ID。所以两个记录在开始时都没有ID。因此,无法在首次创建此请求时序列化关系。获取“model.session”。保存。您的API对该请求的响应良好。响应包括此记录没有任何相关说话人的信息。ember数据使用API返回的信息更新其存储。此更新包括删除以前创建的关系。第二个create请求this.get'model.speaker'。save序列化关系,但不存在,因为这是存储中的当前值


如果是这种情况,您只需在分配关系之前创建一条记录,然后保存另一条记录,这将在服务器上保持关系。

正如@jelhan所建议的,我必须先在模型上保存,然后添加关系。以下代码有效:

    import Controller from '@ember/controller';
export default Controller.extend({
  actions: {
    async save() {
      try {
        this.set('isLoading', true);
        await this.get('model.speaker').save();
        this.get('model.speaker.sessions').pushObject(this.get('model.session'));
        await this.get('model.session').save();
        await this.get('model.speaker').save();
        this.get('notify').success(this.get('l10n').t('Your session has been saved'));
        this.transitionToRoute('events.view.sessions', this.get('model.event.id'));
      } catch (e) {
        this.get('notify').error(this.get('l10n').t('Oops something went wrong. Please try again'));
      }
    }
  }
});

保存记录时,您在“网络”选项卡中看到了什么?关系id是否包含在请求有效负载中?@dwenzel否,事实上,在添加和保存相应的对象后,我还创建了一个console.log,但没有添加另一个对象。我认为默认序列化程序应该是这样的。您需要修改序列化程序,因为默认情况下,只有belongsTo关系被序列化。@Lux您能详细说明一下吗?