Backbone.js 什么';将行为附加到流星集合的最佳方式是什么?
在Meteor中,当您从数据库检索记录时,它只是一条记录。因此,如果我有一个名为Backbone.js 什么';将行为附加到流星集合的最佳方式是什么?,backbone.js,model,meteor,behavior,Backbone.js,Model,Meteor,Behavior,在Meteor中,当您从数据库检索记录时,它只是一条记录。因此,如果我有一个名为Dogs的集合,dog可能有fur:'brown'或breath:'doomy',但它没有bark()方法 显然,我可以创建一些函数,这些函数期望将dog作为参数,然后对该dog执行操作。我甚至可以将所有这些函数封装到一个构造函数中。我并不热衷于这种方法,但如果有人有一种干净而明智的方法来做这件事,我会洗耳恭听 我的另一个想法是把狗包在主干中。这可能很有趣,因为fetch和save可以被重新定义为执行find和ins
Dogs
的集合,dog
可能有fur:'brown'
或breath:'doomy'
,但它没有bark()
方法
显然,我可以创建一些函数,这些函数期望将dog
作为参数,然后对该dog
执行操作。我甚至可以将所有这些函数封装到一个构造函数中。我并不热衷于这种方法,但如果有人有一种干净而明智的方法来做这件事,我会洗耳恭听
我的另一个想法是把狗
包在主干中。这可能很有趣,因为fetch
和save
可以被重新定义为执行find
和insert
或update
,您也可以在那里定义您的所有行为,但我已经了解到这类事情通常是不鼓励的
有正确的方法吗?是否有一款流星模型正式投入使用?其他人是如何解决这个问题的
编辑
对于那些在接受答案一年多后提出这个问题的人:在我使用这个编辑时,它有一些改进,这些改进在被接受答案链接的博客文章中提到
我目前正在为存储库做贡献,以使结果集更像关系。希望其他人能够使用它,并愿意贡献有用的功能
编辑
另一个答案建议在创建集合时使用transform
属性。虽然我肯定更喜欢一些我自己并不需要构建的东西,但这个特性增加了很多可能性,我希望任何正在为Meteor开发ORM的团队都能从核心上利用这一点
解释如何使用转换
属性
还有,我还在用它。它支持验证和声明关系。我还为此包添加了一些功能,因此,如果一块板有许多块,board.pieces().create(attributes)
将使用给定的属性保存一条新的块
记录,并将自动与板
关联。在我见过的各种解决方案中,这似乎是最全面的解决方案。虽然可能存在问题,但您现在可以做一些事情:
有一个是Mario Uhler写的,很像activerecord,很不错,用咖啡脚本写的:
还有一个由Tom Coleman制作的社区包,它对模型非常有帮助:,您可能需要将其添加为一个包
当然,正如你所建议的。我个人使用js原型,但并不是每个人都喜欢,我只是使用了它们,这样在meteor的模型系统出现时很容易转换,也很容易在客户端和服务器之间共享,而无需添加太多的包。这是覆盖meteor.Collection以支持对象方法的开始
Meteor.Kollection = Meteor.Collection;
Meteor.Kollection.extend = function(constructor) {
var parent = this;
var child = function() {
Meteor.Kollection.apply(this, arguments);
constructor.apply(this, arguments);
};
_.extend(child, parent);
function __proto__() { this.constructor = child; };
__proto__.prototype = parent.prototype;
child.prototype = new __proto__;
return child;
};
Meteor.Collection = Meteor.Kollection.extend(function(name, options) {
if (options && options.defaults) {
this.defaults = options.defaults;
}
});
Meteor.Collection.prototype.applyDefaults = function(attrs) {
return _.defaults(attrs, this.defaults);
};
Meteor.Collection.prototype.create = function(attrs) {
if (typeof attrs !== "object") attrs = {};
return this.applyDefaults(attrs);
};
Meteor.Collection.prototype.findOne = function(selector, options) {
var object = Meteor.Kollection.prototype.findOne.apply(this, arguments);
return this.applyDefaults(object);
};
您可能会注意到新的collection.create方法,并且该collection.findOne已被重写。我想所有collection.*方法都需要重写,但这只是一个开始
那么你能用这个做什么呢
var Dogs = new Meteor.Collection("dogs", { defaults: {
barkSound: "ruff",
bark: function() {
console.log(this.barkSound);
}
}});
if (Meteor.isClient) {
var regularDog = Dogs.create();
regularDog.bark(); // ruff
var smallDog = Dogs.create({
barkSound: "yip"
});
smallDog.bark(); // yip
Dogs.insert(smallDog, function(error, id) {
Dogs.findOne(id).bark(); // yip
});
});
我不太清楚这是怎么发生的,但是对象中的任何函数在插入时都会被删除。因此,我们可以直接将这些方法应用于对象。首先,通过传入一个具有defaults
属性的对象来创建集合。此属性可以包括属性或方法。若要为给定集合创建新对象,请使用collection.create(attrs),其中attrs是一个选项参数,包括附加的或重写的属性和方法。您可以使用集合中的transform
参数用自定义函数重载对象
var Dogs = new Meteor.Collection("dogs",
{
transform:function(entry)
{
entry.bark = function(){ console.log(this.barkSound);};
return entry;
}
});
然后:
奖励:如果出于任何原因,您希望使用Andrew Ferk提出的类似概念,只需使用u.defaults(object,*defaults)函数即可
var defaults = {
barkSound: "ruff",
bark: function() {
console.log(this.barkSound);
}
}
Dogs = new Meteor.Collection("dogs",
{
transform: function(object) {
return _.defaults(object, defaults);
}
});
对于Meteor来说,这是一个相对古老的问题,但我认为通过实施Flavien Volken的建议,符合您想要实现的目标。也许它对最近在这里闲逛的人有用。是对流星模型这个老问题的新答案。作者有更多的功能计划,是在工作和其他著名的流星包作者的支持。唯一的缺点可能是它有点流血
天文学也是流星包装/模块化风格建筑的一个主要例子。除了@Flavien Volken的答案之外,您还可以将参数传递给已添加到集合中的方法
Car = new Mongo.Collection('car', {
transform: function(entry) {
entry.is_watched = function(userId) {
var is_watched = false;
if (entry.watchList) {
for (var i in entry.watchList) {
if (entry.watchList[i].userId == userId) {
is_watched = true;
break;
}
}
}
return is_watched;
};
return entry;
}
});
在模板中(传递登录用户的id):
谢谢你的回复。如果不太麻烦的话,你能提供一个简单的例子说明如何利用js原型来解决这个问题吗?我会在一段时间内更新这个,我只需要清理一下原型,一个bitI决定使用的Minimongoid,这很符合实际情况:-)我不明白为什么集合的转换参数不够。谢谢@0,很抱歉我没有早点看到这个。我已经用一些关于transform
的注释更新了OP,这绝对值得一提。值得一提的是软件包。@DanDascalescu,谢谢你的链接!它不太适合我所寻找的,但在其他方面对我非常有用。非常感谢!这看起来是正确的、官方的做法。我要用这个。这是一个很棒的解决方案,谢谢!!!现在完全改变了我的流星代码。我怎么会在文档中漏掉这一点呢???在这个主题上贴上更多的例子:谢谢,我很感激被新技术更新。我仍然在使用minimongoid(),它支持像has\u one
和behings这样的声明
Car = new Mongo.Collection('car', {
transform: function(entry) {
entry.is_watched = function(userId) {
var is_watched = false;
if (entry.watchList) {
for (var i in entry.watchList) {
if (entry.watchList[i].userId == userId) {
is_watched = true;
break;
}
}
}
return is_watched;
};
return entry;
}
});
{{# if is_watched currentUser._id }}
Watched
{{ else }}
Not watched
{{/ if }}