嵌入多对多关系-如果一个新对象还不存在,则添加一个新的对象
Ember many to many relationship - add a new object if one does not already exist
我有两个彼此有多对多关系的模型-第一个是"配方",第二个是"标签":
App.ApplicationAdapter = DS.FixtureAdapter.extend({});
App.Recipe = DS.Model.extend({
title: attr('string'),
source: attr('string'),
notes: attr('string'),
isFavourite: attr('boolean', {defaultValue: false}),
tags: hasMany('tag', { async: true })
});
App.Tag = DS.Model.extend({
name: attr('string'),
recipes: hasMany('recipe', { async: true })
});
在我的模板中,我有一个为食谱添加标签的输入。用户可以添加一个标记,也可以通过用逗号分隔每个标记来添加多个标记。
{{input type="text" enter="AddTags" placeholder="add a tag (or two!)"}}
这在我的RecipeController:中调用"AddTags"
App.RecipeController = Ember.ObjectController.extend({
actions: {
AddTags: function(tags){
var store = this.store;
var thisRecipe = this.get('model');
var thisRecipeTags = thisRecipe.get('tags');
var addedTags = tags.split(',');
for (i = 0; i < addedTags.length; i++) {
tag = store.createRecord('tag', {
name: addedTags[i]
});
thisRecipeTags.addObject(tag);
}
}
}
});
这非常有效-但是-我想重构函数,这样只有在不存在同名标签的情况下才能创建新标签:
AddTags: function(tags){
var store = this.store;
var thisRecipe = this.get('model');
var thisRecipeTags = thisRecipe.get('tags');
var addedTags = tags.split(',');
for (i = 0; i < addedTags.length; i++) {
// If exisiting tag where name == addedTags[i]
tag = existing tag object here
// Else create a new tag
tag = store.createRecord('tag', {
name: addedTags[i]
});
thisRecipeTags.addObject(tag);
}
}
我该怎么做?
更新:我在这里用相关代码建立了一个JS bin:http://jsbin.com/kixexe/1/edit?js,输出
在中进行演示
现在来解释一下。。。
您在jsbin中使用DS.FixtureAdapter
,如果要像按名称查询一样查询fixture(请参见此处),则需要实现queryFixtures
方法。这方面的快速实现可以如下:
MyApp.TagAdapter = DS.FixtureAdapter.extend({
queryFixtures: function(fixtures, query){
var result = [];
var tag = fixtures.findBy('name', query.name);
if(tag){
result.push(tag);
}
return result;
}
});
当你查询商店时,你会得到一个承诺,你可以使用then()
进入
如果你什么都没找到,你可以继续做你以前的事情。。。
如果您确实找到了一个现有的标签,您可以将其添加到其他标签中,然后保存标签和配方记录,因为这是一种多对多的关系。
更新
此处更新解决方案
你的for
循环变得很混乱,尤其是在使用promise时,这通常不是你想要的。相反,Ember有一种更典型/功能性的forEach()
方法。我还修剪了标签末尾的空白,因为这可能是您使用map()
所想要的。请参阅此处了解有关map()
和forEach()
的更多信息
// trim whitespace
var addedTags = tags.split(',').map(function(str){
return str.replace(/^'s+|'s+$/gm,'');
});
// loop through tags
addedTags.forEach(function(tagName){
store.find('tag', { name: tagName }).then(function(results){
if(results.content.length){
thisRecipeTags.addObject(results.content[0]);
thisRecipeTags.save();
thisRecipe.save();
}
else {
var tag = store.createRecord('tag', {
name: tagName
});
thisRecipeTags.addObject(tag);
thisRecipeTags.save();
thisRecipe.save();
}
});
});
更新#2
标记未正确删除。因为这是一个双向映射,显然你需要从食谱中删除标签(你正在做),也需要从标签中删除食谱,你没有做。更新后的代码如下:
removeTag: function(tag) {
var recipe = this.get('model');
recipe.get('tags').removeObject(tag);
tag.get('recipes').removeObject(recipe.get('id'));
tag.save();
recipe.save();
},
工作(希望这次是真的;)这里的解决方案
您可以如下搜索现有标签:
var existing = store.find('tag', { name: addedTags[i] });
因此,你可以有如下逻辑:
AddTags: function(tags){
var store = this.store;
var thisRecipe = this.get('model');
var thisRecipeTags = thisRecipe.get('tags');
var addedTags = tags.split(',');
for (i = 0; i < addedTags.length; i++) {
var existing = store.find('tag', { name: addedTags[i] });
if(existing){
tag = existing
} else {
tag = store.createRecord('tag', {
name: addedTags[i]
});
}
thisRecipeTags.addObject(tag);
}
}
我现在还不能对此进行测试,所以它可能需要一些更改来解释承诺等——但这应该或多或少能满足你的需求。
- 节点导出返回一个空对象
- 我可以在json对象中添加一个函数吗
- Javascript,访问一个主要对象模块模式中的每个对象
- 如果使用 lodash 将属性存在于另一个对象中,则向对象添加属性
- Javascript(Angular)从一个对象数组到第二个数组查找值
- 从HTTPGET返回一个自定义对象列表,以便在Angular 2应用程序中使用
- 为什么要包装每一个原型“;类“;JS中具有匿名函数的对象
- 要求定义另一个文件中的对象
- 对一个对象使用reduce可以返回一个没有't在数组中包含目标字母
- AngularJS&JSON-从Previous&下一个对象
- jQuery$.inArray()总是返回-1和一个对象数组
- 在创建对象后附加一个jquery事件
- javascript处理一个对象数组以获得一个新的对象数组
- javascript函数,它接受两个输入:一个对象和一个键,并返回对象中该键的相应值
- 你能用来自数组的属性名称生成一个对象吗
- 是不是;t一个原型对象一个实例
- 有没有一种方法可以在不修改Object.prototype的情况下给所有对象一个方法?
- 给svg对象一个描边
- 你能用javascript给一个对象一个键吗
- JavaScript使对象一个全局窗口对象?(无冲突功能)