Coffeescript类查找或创建mongo文档

时间:2013-08-26 01:44:18

标签: javascript mongodb coffeescript mongojs

我正在尝试编写一个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')

3 个答案:

答案 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

演示:http://jsfiddle.net/ambiguous/wLjz3/

答案 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'