Есть ли способ показать идентификаторы связанных моделей без загрузки или встраивания данных

Насколько я понимаю, использование serializeIds: 'always' предоставит мне эти данные, но это не так.

Вот чего я жду:

{
  id="1"
  title="some title"
  customerId="2"
}

Вместо этого я получаю следующий результат:

{
  id="1"
  title="some title"
}

Мой код выглядит примерно так:

import {
  Server,
  Serializer,
  Model,
  belongsTo,
  hasMany,
  Factory
} from "miragejs";
import faker from "faker";

const ApplicationSerializer = Serializer.extend({
  // don't want a root prop
  root: false,
  // true required to have root:false
  embed: true,
  // will always serialize the ids of all relationships for the model or collection in the response
  serializeIds: "always"
});

export function makeServer() {
  let server = newServer({
    models: {
      invoice: Model.extend({
        customer: belongsTo()
      }),
      customer: Model.extend({
        invoices: hasMany()
      })
    },

    factories: {
      invoice: Factory.extend({
        title(i) {
          return `Invoice ${i}`;
        },
        afterCreate(invoice, server) {
          if (!invoice.customer) {
            invoice.update({
              customer: server.create("customer")
            });
          }
        }
      }),
      customer: Factory.extend({
        name() {
          let fullName = () =>
            `${faker.name.firstName()} ${faker.name.lastName()}`;

          return fullName;
        }
      })
    },

    seeds(server) {
      server.createList("invoice", 10);
    },

    serializers: {
      application: ApplicationSerializer,
      invoice: ApplicationSerializer.extend({
        include: ["customer"]
      })
    },

    routes() {
      this.namespace = "api";

      this.get("/auth");
    }
  });
}

Изменение конфигурации на root: true, embed: false, обеспечивает правильный вывод в invoice модели, но добавляет корень и загружает неопубликованные версии клиента, что мне не нужно.

1 ответ

Решение

Вы столкнулись со странным поведением, как serializeIds взаимодействует с embed.

Во-первых, непонятно, зачем нужно устанавливать embed: trueкогда вы просто пытаетесь отключить рут. Причина в том, чтоembedпо умолчанию установлено значение false, поэтому, если вы удалите корень и попытаетесь включить связанные ресурсы, Mirage не знает, где их разместить. Это запутанное сочетание опций, и Mirage действительно должен иметь разные "режимы", которые это учитывают.

Во-вторых, кажется, что когда embed правда, Мираж в основном игнорирует serializeIdsвариант, так как он думает, что ваши ресурсы всегда будут встроены. (Идея здесь в том, что внешний ключ используется для получения связанных ресурсов по отдельности, но когда они встроены, они всегда объединяются.) Это также сбивает с толку и не обязательно так. Я открыл проблему отслеживания в Mirage, чтобы помочь решить эти проблемы.

Что касается вас сегодня, лучший способ решить эту проблему - это оставить root к истине и embed false, которые являются значениями по умолчанию, так что serializeIds работает правильно, а затем просто напишите свой serialize() функция удаления ключа для вас:

const ApplicationSerializer = Serializer.extend({
  // will always serialize the ids of all relationships for the model or collection in the response
  serializeIds: "always",

  serialize(resource, request) {
    let json = Serializer.prototype.serialize.apply(this, arguments);

    let root = resource.models ? this.keyForCollection(resource.modelName) : this.keyForModel(resource.modelName)

    return json[root];
  }
});

Вы сможете проверить это на обоих /invoices а также /invoices/1.

Посетите WIP Inspector и вставьте следующую конфигурацию на вкладку Config, затем попробуйте сделать запрос для каждого URL-адреса.

import {
  Server,
  Serializer,
  Model,
  belongsTo,
  hasMany,
  Factory,
} from "miragejs";
import faker from "faker";

const ApplicationSerializer = Serializer.extend({
  // will always serialize the ids of all relationships for the model or collection in the response
  serializeIds: "always",

  serialize(resource, request) {
    let json = Serializer.prototype.serialize.apply(this, arguments);

    let root = resource.models ? this.keyForCollection(resource.modelName) : this.keyForModel(resource.modelName)

    return json[root];
  }
});

export default new Server({
  models: {
    invoice: Model.extend({
      customer: belongsTo(),
    }),
    customer: Model.extend({
      invoices: hasMany(),
    }),
  },

  factories: {
    invoice: Factory.extend({
      title(i) {
        return "Invoice " + i;
      },
      afterCreate(invoice, server) {
        if (!invoice.customer) {
          invoice.update({
            customer: server.create("customer"),
          });
        }
      },
    }),
    customer: Factory.extend({
      name() {
        return faker.name.firstName() + " " + faker.name.lastName();
      },
    }),
  },

  seeds(server) {
    server.createList("invoice", 10);
  },

  serializers: {
    application: ApplicationSerializer,
  },

  routes() {
    this.resource("invoice");
  },
});

Надеюсь, это проясняет ситуацию + извините за запутанные API!

Другие вопросы по тегам