Данные Ember принадлежат к асинхронным отношениям, исключенным из сериализации createRecord() save()
Редактировать 16.11.14: Информация о версии
DEBUG: Ember : 1.7.0 ember-1.7.0.js:14463
DEBUG: Ember Data : 1.0.0-beta.10+canary.30d6bf849b ember-1.7.0.js:14463
DEBUG: Handlebars : 1.1.2 ember-1.7.0.js:14463
DEBUG: jQuery : 1.10.2
Я бьюсь головой о стену, пытаясь сделать что-то, что, на мой взгляд, должно быть довольно простым с данными о тлеющих углях и угасающих угрях, но мне пока не повезло.
По сути, я хочу использовать данные сервера для заполнения <select>
выпадающее меню. Когда форма отправлена, модель должна быть создана на основе данных, выбранных пользователем. Затем модель сохраняется с данными ember и пересылается на сервер в следующем формате:
{
"File": {
"fileName":"the_name.txt",
"filePath":"/the/path",
"typeId": 13,
"versionId": 2
}
}
Проблема в том, что typeId и versionId не учитываются, когда отношение модели определяется как асинхронное, например:
App.File = DS.Model.extend({
type: DS.belongsTo('type', {async: true}),
version: DS.belongsTo('version', {async: true}),
fileName: DS.attr('string'),
filePath: DS.attr('string')
});
Часть, которая сбивает меня с толку, и, вероятно, где мои ошибки лежат, это контроллер:
App.FilesNewController = Ember.ObjectController.extend({
needs: ['files'],
uploadError: false,
// These properties will be given by the binding in the view to the
//<select> inputs.
selectedType: null,
selectedVersion: null,
files: Ember.computed.alias('controllers.files'),
actions: {
createFile: function() {
this.createFileHelper();
}
},
createFileHelper: function() {
var selectedType = this.get('selectedType');
var selectedVersion = this.get('selectedVersion');
var file = this.store.createRecord('file', {
fileName: 'the_name.txt',
filePath: '/the/path'
});
var gotDependencies = function(values) {
//////////////////////////////////////
// This only works when async: false
file.set('type', values[0])
.set('version', values[1]);
//////////////////////////////////////
var onSuccess = function() {
this.transitionToRoute('files');
}.bind(this);
var onFail = function() {
this.set('uploadError', true);
}.bind(this);
file.save().then(onSuccess, onFail);
}.bind(this);
Ember.RSVP.all([
selectedType,
selectedVersion
]).then(gotDependencies);
}
});
Когда для async установлено значение false, угасающие ручки createRecord().save()
POST запрашивает правильно.
Когда async имеет значение true, ember прекрасно обрабатывает GET-запросы с несколькими запросами, но НЕ добавляет отношения ownTo к файлу JSON во время createRecord().save()
, Только основные свойства сериализуются:
{"File":{"fileName":"the_name.txt","filePath":"/the/path"}}
Я понимаю, что этот вопрос уже задавался, но пока не нашел удовлетворительного ответа и не нашел ничего, что отвечало бы моим потребностям. Итак, как я могу получить правильную сериализацию отношения отношение к?
Просто чтобы быть уверенным, что все здесь, я добавлю пользовательскую сериализацию, которую я имею до сих пор:
App.ApplicationSerializer = DS.RESTSerializer.extend({
serializeIntoHash: function(data, type, record, options) {
var root = Ember.String.capitalize(type.typeKey);
data[root] = this.serialize(record, options);
},
keyForRelationship: function(key, type){
if (type === 'belongsTo') {
key += "Id";
}
if (type === 'hasMany') {
key += "Ids";
}
return key;
}
});
App.FileSerializer = App.ApplicationSerializer.extend(DS.EmbeddedRecordsMixin, {
attrs: {
type: { serialize: 'id' },
version: { serialize: 'id' }
}
});
И выберите:
{{ view Ember.Select
contentBinding="controller.files.versions"
optionValuePath="content"
optionLabelPath="content.versionStr"
valueBinding="controller.selectedVersion"
id="selectVersion"
classNames="form-control"
prompt="-- Select Version --"}}
При необходимости я добавлю другие маршруты и контроллеры (FilesRoute, FilesController, VersionsRoute, TypesRoute)
РЕДАКТИРОВАТЬ 16/16/14
У меня есть рабочее решение (хак?), Которое я нашел на основе информации в двух соответствующих темах:
1) Как асинхронные отношения должны быть сериализованы?
2) Поддерживает ли async соответствующее назначение модели?
По сути, все, что мне нужно было сделать, это переместить Ember.RSVP.all()
после get()
по свойствам:
createFileHelper: function() {
var selectedType = this.get('selectedType');
var selectedVersion = this.get('selectedVersion');
var file = this.store.createRecord('file', {
fileName: 'the_name.txt',
filePath: '/the/path',
type: null,
version: null
});
file.set('type', values[0])
.set('version', values[1]);
Ember.RSVP.all([
file.get('type'),
file.get('version')
]).then(function(values) {
var onSuccess = function() {
this.transitionToRoute('files');
}.bind(this);
var onFail = function() {
alert("failure");
this.set('uploadError', true);
}.bind(this);
file.save().then(onSuccess, onFail);
}.bind(this));
}
Так что мне нужно было get()
свойства, которые принадлежали отношениям, прежде чем я сохраню модель. Я не знаю, является ли это ошибкой или нет. Может быть, кто-то с большим знанием о emberjs может помочь пролить свет на это.
1 ответ
См. Вопрос для получения более подробной информации, но общий ответ, который я работал для меня при сохранении модели с отношением ownTo (и вам необходимо, чтобы это отношение было сериализовано), заключается в вызове .get()
на свойствах, а затем save()
их в then()
,
Это сводится к этому:
var file = this.store.createRecord('file', {
fileName: 'the_name.txt',
filePath: '/the/path',
type: null,
version: null
});
// belongsTo set() here
file.set('type', selectedType)
.set('version', selectedVersion);
Ember.RSVP.all([
file.get('type'),
file.get('version')
]).then(function(values) {
var onSuccess = function() {
this.transitionToRoute('files');
}.bind(this);
var onFail = function() {
alert("failure");
this.set('uploadError', true);
}.bind(this);
// Save inside then() after I call get() on promises
file.save().then(onSuccess, onFail);
}.bind(this));