Представлено детализированное описание того, как выглядит модель в приложении.

Описание

Модели в ember-приложениях наследуются от класса Ember Data DS.Model.

Модели чаще всего имеют следующую структуру:

// Импорты.
import DS from 'ember-data';
import { Projection } from 'ember-flexberry-data';

var Model = Projection.Model.extend({
  // Собственные атрибуты, мастера, детейлы.
  name: DS.attr('string'),
  someMaster: DS.belongsTo('new-platform-someproject-somemaster', { inverse: 'somemodel', async: false, polymorphic: true }),
  ...

  // Правила валидации.
  validations: {
    name: { presence: true }
    ...
  }
});

// Определение модели-предка (при наличии).
Model.reopenClass({
  _parentModelName: '...' // Указывается имя модели, от которой наследуется данная модель, например 'new-platform-someproject-parent'.
});

// Определение представлений.
Model.defineProjection(
  name: Projection.attr(''),
  someMaster: Projection.belongsTo('new-platform-someproject-somemaster', '', {
    ...
  })
  ...
});

Model.defineProjection(
 ...
});

// Экспорт модели.
export default Model;

Импорты и экспорт соответствуют требованиям синтаксиса ember-cli. Создаваемая модель наследуется от базового технологического класса, определенного в аддоне ember-flexberry-data. Для модели задаются представления.

Существуют также разные подходы к заданию значения по умолчанию для атрибутов модели.

Определение модели

Модели определяются “стандартным” для Ember способом.

Дополнительно в моделях, унаследованных от базовой технологической модели, используются правила валидации модели.

Для атрибутов любых моделей Ember доступны встроенные типы данных string (строка), number (число), boolean (логический тип) и date (дата). Для определения других типов данных в моделях Ember используются трансформации.

Дополнительно к стандартным типам данных в аддоне ember-flexberry-data были добавлены трансформации decimal (вещественный тип), file (тип “Файл”), flexberry-enum (тип для перечислений), guid (тип “GUID”, который используется по умолчанию для первичных ключей).

Подробнее об использовании трансформаций для перечислений можно посмотреть тут.

Пример модели для класса с мастером employee1 типа ‘new-platform-someproject-employee’ и детейлами orders типа ‘new-platform-someproject-order’.

var Model = BaseModel.extend({
  firstName: DS.attr('string'),
  lastName: DS.attr('string'),
  birthDate: DS.attr('date'),
  photo: DS.attr('file'),
  gender: DS.attr('new-platform-someproject-gender'),
  employee1: DS.belongsTo('new-platform-someproject-employee', { inverse: null, async: false }),
  orders: DS.hasMany('new-platform-someproject-order', { inverse: 'employee', async: false }),
});

Первичные ключи в модели

Первичные ключи объекта не задаются в модели явно. В клиентском коде обращения к первичному ключу можно выполнить через свойство id.

Как называется соответствующее свойство на сервере, определяется в сериализаторе.

Тип первичного ключа

Первичные ключи моделей в Ember-приложениях всегда являются строками, но на сервере это поведение можно изменить. При изменении типа первичного ключа на сервере необходимо переопределить статическое свойство idType в классе модели:

import { Projection } from 'ember-flexberry-data';

let Model = Projection.Model.extend({
  // ...
});

Model.reopenClass({
  idType: '...',
});

export default Model;

Устанавливается свойство idType при помощи статической функции defineIdType в базовой технологической модели:

defineIdType: function (newIdType) {
  this.reopenClass({
    idType: newIdType,
  });
},

Вызвать этот метод можно следующим образом:

Model.defineIdType('string');

Тип первичного ключа - это метаданные модели, поэтому свойство idType определено именно в модели, а не, например, в адаптере.

Получить тип ключа можно через метод getMeta утилиты information из аддона ember-flexberry-data.

В языке запросов тип ключа учитывается автоматически, и при построении запросов к OData-бакенду значения ключей в URL запросов “окавычиваются” только в том случае, если тип ключа - string. На данный момент поддерживается 3 типа ключей в клиентской части: string, guid и number. В других случаях при построении запросов к OData-бакенду будет выбрасываться исключение.

inverse-связи

Задание inverse-связи используется, например, при работе с детейлами.

Задание связи от агрегатора к детейлу.

var Model = BaseModel.extend({
  ...
  orders: DS.hasMany('order', { inverse: 'employee', async: false }),
});

Задание связи от детейла к агрегатору.

var Model = BaseModel.extend({
  // ...
  employee: DS.belongsTo('employee', { inverse: 'orders', async: false })
});