- // eslint-disable-next-line ember/no-mixins
- /**
- orm model
- @module mixins
- @submodule model
- */
-
- /**
-
- @example
- import EmberObject from '@ember/object';
- import model, {DS} from 'ember-easy-orm/mixins/model'
-
- const {attr} = DS;
-
- export default EmberObject.extend(model, {
- url: '/v1/food',
- init(){
- this._super(...arguments);
- this.model = {
- 'name': attr('string'),
- 'desc': attr('string'),
- 'pic': attr('array'),
- 'province_id': attr('string'),
- 'city_id': attr('string'),
- 'area_id': attr('string'),
- 'town_id': attr('string'),
- 'country_id': attr('string'),
- 'url': attr('string'),
- 'host': attr('string'),
- 'tag': attr('array'),
- 'user': attr({defaultValue: function(){
- return {name: '', 'gender': ''};
- }})
- };
- }
- })
- */
-
- import { A, isArray } from '@ember/array';
- import Mixin from '@ember/object/mixin';
- import Evented from '@ember/object/evented';
- import EmberObject, { computed } from '@ember/object';
- import { merge } from '@ember/polyfills';
- import { isBlank, isNone } from '@ember/utils';
-
- import ajax from './ajax';
-
- export const DS = {
- attr(type, hash) {
- if (typeof type === 'object') {
- hash = type;
- type = undefined;
- }
-
- if (typeof hash === 'object') {
- if (hash.defaultValue !== undefined) {
- return hash.defaultValue;
- }
- }
-
- switch (type) {
- case 'string':
- return '';
- case 'boolean':
- return true;
- case 'number':
- return 0;
- case 'array':
- return A;
- }
-
- return null;
- },
- };
-
- /**
- mixin in ORM model
- @public
- @class model
- **/
- export default Mixin.create(ajax, Evented, {
- /**
- The api host, default is current host
- @property {String} host
- @default ""
- */
- host: '',
-
- /**
- The api namespace like /v1 /v2
- @property {String} namespace
- @default ""
- */
- namespace: '',
-
- /**
- The response data business logic root key like: {'code': 0, 'resp':{'user':[]}, 'msg':''}, the resp is is the rootKey
- @property {String} rootKey
- @default ""
- */
- rootKey: '',
-
- /**
- The api url. If rootURL ends with slash , the url should not starts with slash
- @property {String} url
- @default ""
- */
- url: '',
-
- /**
- The model object primary key
- @property {String} primaryKey
- @default "_id"
- */
- primaryKey: '_id',
-
- /**
- The object is for extract response data {user: [], comment:[], avatar: {}}
- @property {Object} displayModel
- @default null
- */
- displayModel: null,
-
- /**
- url for find method request, use this method to custome find url
- @method urlForFind
- @default /host/namespace/?key=params[key]
- @return String
- */
- urlForFind: function () {
- return this.api;
- },
-
- /**
- url for findOne method request, use this method to custome findOne url
- @method urlForFindOne
- @default /{host}/{namespace}/{id}
- @return String
- */
- urlForFindOne: function (id) {
- return this.api + '/' + id;
- },
- /**
- url for save method request, use this method to custome create and update url
- @method urlForSave
- @param id object primary key
- @default /{host}/{namespace}/{id}/
- @return String
- */
- urlForSave: function (id) {
- return id ? this.api + '/' + id : this.api;
- },
-
- /**
- url for delete method request, use this method to custome delete url
- @method urlForDelete
- @default /{host}/{namespace}/{id}
- @param id object primary key
- @return String
- */
- urlForDelete: function (id) {
- return id ? this.api + '/' + id : this.api;
- },
- /**
- make api with host, namespace, url
- @method api
- @property {String} api
- @return {host}{namespace}{url}
- */
- api: computed('host', 'namespace', 'url', function () {
- return this.host + this.namespace + this.url;
- }),
- /**
- save the record to backend when create or update object
- @method save
- @param model model needed to save
- @return {Promise}
- */
- save: function (model) {
- let self = this,
- primaryKey = this.primaryKey,
- url = this.urlForSave(model[primaryKey], model),
- record = {},
- model_keys = Object.keys(this.model);
-
- //filter model data
- for (var i = model_keys.length - 1; i >= 0; i--) {
- let key = model_keys[i];
- if (typeof self.model[key] === 'function') {
- if (typeof model[key] === 'object' && !isArray(model[key])) {
- record[key] = JSON.stringify(model[key]);
- continue;
- }
- }
-
- if (isArray(model[key])) {
- let content = model[key];
- for (let i = 0; i < content.length; i++) {
- if (typeof content[i] === 'object' && content[i]) {
- model[key][i] = JSON.stringify(content[i]);
- }
- }
- }
-
- record[key] = model[key] !== undefined ? model[key] : self.model[key];
- }
-
- //check if is new data
- if (model[primaryKey]) {
- record[primaryKey] = model[primaryKey];
- return this.request.put(url, { data: record }).then(
- function (data) {
- // eslint-disable-next-line no-useless-catch
- try {
- return self.saveSerializer(data);
- } catch (e) {
- throw e;
- }
- },
- function (reason) {
- throw reason;
- }
- );
- }
-
- return this.request.post(url, { data: record }).then(
- function (data) {
- // eslint-disable-next-line no-useless-catch
- try {
- return self.saveSerializer(data);
- } catch (e) {
- throw e;
- }
- },
- function (reason) {
- throw reason;
- }
- );
- },
-
- /**
- create new model with init options and model property
- @method createRecord
- @param {Object} init init data
- @return Object current model
- */
- createRecord: function (init) {
- let record = EmberObject.create();
- Object.keys(this.model).map((key) => {
- if (typeof this.model[key] === 'function') {
- record.set(key, this.model[key].apply());
- } else {
- record.set(key, this.model[key]);
- }
- });
-
- if (typeof init === 'object') {
- merge(record, init);
- }
-
- return record;
- },
-
- /**
- delete the record from backend
- @method deleteRecord
- @param {Object} model
- @param {Object} data passed to backend server as extra params
- @return Promise
- */
- deleteRecord: function (model, data) {
- let self = this,
- _id =
- typeof model === 'string' || typeof model === 'number'
- ? model
- : model[this.primaryKey],
- url = this.urlForDelete(_id, data),
- options = data ? { data: data } : {};
-
- return this.request.delete(url, options).then(
- function (data) {
- // eslint-disable-next-line no-useless-catch
- try {
- return self.deleteSerializer(data);
- } catch (e) {
- throw e;
- }
- },
- function (reason) {
- throw reason;
- }
- );
- },
- /**
- find the records from backend according to params
- @method find
- @param {Object} params query params
- @return Promise
- */
- find: function (params) {
- let self = this,
- url = this.urlForFind(params),
- filterParams = this._filterParams(params),
- options = filterParams ? { data: filterParams } : {};
-
- return this.request.get(url, options).then(
- function (data) {
- // eslint-disable-next-line no-useless-catch
- try {
- return self.findSerializer(data);
- } catch (e) {
- throw e;
- }
- },
- function (reason) {
- throw reason;
- }
- );
- },
-
- /**
- find only one according to primary id
- @method findOne
- @param {String} id primary key
- @param {Object} data query parameter append to url
- @return Promise
- */
- findOne: function (id, data) {
- let url = this.urlForFindOne(id, data),
- self = this,
- options = data ? { data: data } : {};
-
- return this.request.get(url, options).then(
- function (data) {
- // eslint-disable-next-line no-useless-catch
- try {
- return self.findOneSerializer(data);
- } catch (e) {
- throw e;
- }
- },
- function (reason) {
- throw reason;
- }
- );
- },
- /**
- filter request params
- @private
- @method _filterParams
- @param {Object} params
- @return Object filtered params
- */
- _filterParams: function (params) {
- if (!params) {
- return;
- }
- Object.keys(params).map((k) => {
- if (isBlank(params[k])) {
- delete params[k];
- }
- });
- return params;
- },
- /**
- find serializer
- @method findSerializer
- @param {Object} data response data from backend
- @return serializer data
- */
- findSerializer: function (data) {
- let result = {};
- if (this.displayModel) {
- let objectKeys = Object.keys(this.displayModel);
- for (let i = 0; i < objectKeys.length; i++) {
- let key = objectKeys[i];
- let keyAttr = this.displayModel[key];
- if (keyAttr === 'array') {
- result[key] = this.to_array(data[key]);
- continue;
- }
- if (keyAttr === 'object') {
- result[key] = this.to_object(data[key]);
- continue;
- }
- result[key] = data[key];
- }
- return result;
- }
-
- //data is null or undefined
- if (isNone(data)) {
- console.warn('findSerializer response data is null');
- return this.to_array();
- }
-
- // rootKey is empty
- if (!this.rootKey) {
- return this.to_array(data);
- }
-
- // response data must be array
- if (!isArray(data[this.rootKey])) {
- console.warn(
- 'findSerializer parsedData is not array',
- data,
- this.rootKey
- );
- return this.to_array();
- }
-
- return this.to_array(data[this.rootKey]);
- },
- /**
- serializer for findOne method
- @method findOneSerializer
- @param {Object} data response data from backend
- @return serializer data
- */
- findOneSerializer: function (data) {
- //data is null or undefined
- if (isNone(data)) {
- console.warn('findOneSerializer response data is null');
- return this.to_object();
- }
-
- // rootKey is empty
- if (!this.rootKey) {
- return data;
- }
-
- // parsedObject must be object
- if (isNone(data[this.rootKey])) {
- console.warn('findOneSerializer parsedObject is null');
- return this.to_object();
- }
-
- return this.to_object(data[this.rootKey]);
- },
- to_array: function (data) {
- return A(data || []);
- },
- to_object: function (data) {
- return EmberObject.create(data || {});
- },
- /**
- serializer for save method
- @method saveSerializer
- @param {Object} data response data from backend
- @return serializer data
- */
- saveSerializer: function (data) {
- return data;
- },
- /**
- serializer for delete
- @method deleteSerializer
- @param {Object} data response data from backend
- @return serializer data
- */
- deleteSerializer: function (data) {
- return data;
- },
- init: function () {
- this._super(...arguments);
- if (typeof this.rootKey !== 'string') {
- throw new Error(`rootKey only allow string type, now is ${this.rootKey}`);
- }
- },
- });
-
-