我正在尝试编写一个coffeescript类,当从它构造一个新对象时,它会检查是否传递了一个ID。如果是这样,请尝试查找匹配的文档并从中填充对象。如果未传递任何ID,则生成新ID以创建新文档。我正在使用mongojs
连接到我的mongodb。但是,当我从TestObject类创建一个新对象时,它会抛出一个错误,集合名称需要是一个字符串。我将@collection设置为该类的字符串,因此我在console.log中将@collection属性及其未定义。什么事情发生在这里,我怎么能让这个工作?
class MongoObject
@collection
constructor: (id) ->
@_id = if typeof id is 'undefined' then require('node-uuid').v4() else id
@db = require('mongojs') config.mongo_server, [@collection]
@db[@collection].findOne
_id: @_id,
(error, story) ->
# Matching document found. Import data from document
if not error and story
for field, value of story
@[field] = value if field is not '_id'
# Matching document not found. Creating new one
if not error and not story
@db[@collection].save
id: @id
# Error occured
if error and not story
console.error error
return
class TestObject extends MongoObject
@collection = 'TestObjects'
constructor: (id) ->
super('TestObject')
修改
重新阅读我的代码,明确指出构造函数和@collection在MongoObject中未定义的问题。有没有更好的方法来做到这一点?我可以创建一个setupDB
方法,并在每个类的构造函数中调用它,在超级调用之后扩展MongoObject,但不是我希望的。
修改2
我修改了我的代码。但是我现在收到constructor
未定义的错误。当我查看已编译的javascript时,它指向MongoObject代码顶部的constructor;
。奇怪的是,coffeescript没有放var constructor;
这通常会发生什么。我发布了翻译的javascript仅供参考
的CoffeeScript
class MongoObject
collection: undefined
constructor: (id) ->
@_id = if typeof id is 'undefined' then require('node-uuid').v4() else id
@db = require('mongojs') config.mongo_server, [@collection]
@db[@collection].findOne
_id: @_id,
(error, story) ->
# Matching document found. Import data from document
if not error and story
for field, value of story
@[field] = value if field is not '_id'
# Matching document not found. Creating new one
if not error and not story
@db[@collection].save
id: @id
# Error occured
if error and not story
console.error error
return
class TestObject extends MongoObject
collection = 'TestObjects'
constructor: (id) ->
super('TestObject')
的Javascript
MongoObject = (function() {
MongoObject.prototype.collection = void 0;
function MongoObject(id) {
this._id = typeof id === 'undefined' ? require('node-uuid').v4() : id;
this.db = require('mongojs')(config.mongo_server, [this.collection]);
this.db[this.collection].findOne({
_id: this._id
}, function(error, story) {
var field, value;
if (!error && story) {
for (field in story) {
value = story[field];
if (field === !'_id') {
this[field] = value;
}
}
}
if (!error && !story) {
this.db[this.collection].save({
id: this.id
});
}
if (error && !story) {
console.error(error);
}
});
}
return MongoObject;
})();
TestObject = (function(_super) {
var collection;
__extends(TestObject, _super);
collection = 'TestObjects';
function TestObject(id) {
TestObject.__super__.constructor.call(this, 'TestObject');
}
return TestObject;
})(MongoObject);
编辑3
根据我的评论更新了我的代码。它说@constructor.collection
在
@db[@constructor.collection].save
id: @id
我假设它因为它在save的回调函数中。迈出了一步,退后两步。
修改后的代码
class MongoObject
@collection
constructor: (id) ->
@_id = if typeof id is 'undefined' then require('node-uuid').v4() else id
@db = require('mongojs') config.mongo_server, [@constructor.collection]
@db[@constructor.collection].findOne
_id: @_id,
(error, story) ->
# Matching document found. Import data from document
if not error and story
for field, value of story
@[field] = value if field is not '_id'
# Matching document not found. Creating new one
if not error and not story
@db[@constructor.collection].save
id: @id
# Error occured
if error and not story
console.error error
return
class TestObject extends MongoObject
@collection: 'TestObjects'
constructor: (id) ->
super('TestObject')
答案 0 :(得分:1)
我认为你对班级@
的含义感到困惑。一个简化的例子应该有帮助,这个CoffeeScript:
class B
@p: 'b'
与此JavaScript相同:
var B = (function() {
function B() {}
B.p = 'b';
return B;
})();
因此,您可以看到p
是一个直接附加到C
类/函数的类属性。但是当你进入某个方法时,例如constructor
,@
会引用该实例,因此,在您的情况下,@collection
将为undefined
,因为您正在定义{ {1}}作为类属性。
您可能希望collection
成为实例属性:
collection
演示:http://jsfiddle.net/ambiguous/TzK5E/
或者,您可以将class MongoObject
collection: undefined
constructor: (id) ->
# @collection is what you expect it to be in here
class TextObject extends MongoObject
collection: 'TextObject'
作为类属性并通过@constructor
引用它:
collection
答案 1 :(得分:0)
我相信你会想要使用稍微不同的语法来引用collection
名称:
class MongoObject
@collection
constructor: (id) ->
alert @constructor.collection
class TestObject extends MongoObject
@collection = 'TestObjects'
constructor: (id) ->
super('TestObject')
t = new TestObject
提醒"TestObjects"
关键是使用@constructor.collection
。
答案 2 :(得分:0)
这是我最终解决的问题
class MongoObject
@collection
constructor: (id) ->
@_id = if typeof id is 'undefined' then require('node-uuid').v4() else id
@db = require('mongojs') config.mongo_server, [@constructor.collection]
@db[@constructor.collection].findOne
_id: @_id,
(error, doc) =>
# Matching document found. Import data from document
if not error and doc
console.log 'Document found. Updating.'
for field, value of doc
@[field] = value if field is not '_id'
# Matching document not found. Creating new one
if not error and not doc
console.log 'No document found. Creating.'
@db[@constructor.collection].save
_id: @_id
# Error occured
if error and not doc
console.error error
return
class TestObject extends MongoObject
@collection: 'TestObjects'