2012-06-27 3 views
2

Я пытаюсь добавить некоторые функции в магистраль, чтобы я мог общаться с mongodb. Теперь я знаю, что это не будет работать на стороне клиента; Тем не менее, мне действительно нравятся функциональные возможности базовой линии для логики модели на стороне сервера. Я заметил, что я буду выполнять кучу повторной работы, если я буду добавлять одинаковые функциональные возможности для каждой модели, поэтому решил создать файл «app_model», чтобы продлить магистраль, когда я сервер. Я также не хочу переопределять стандартные функции Backbone, потому что они будут полезны на стороне клиента.Добавление дополнительных функций в базовые модели

Итак, давайте этот класс пользователей, например:

var Backbone = require('./app_model'); 

var User = Backbone.Model.extend({ 
    name : "users", 
    defaults: function() { 
     return { 
      username: "default", 
      role: 2, 
      created: new Date(), 
      updated: new Date(), 
      logged: new Date() 
     }; 
    }, 
    idAttribute: "username", 
    /** 
    * A predefined listing of user roles 
    */ 
    userRoles: [ 
     "admin", //0 
     "author", //1 
     "user" //2 
    ], 
    initialize: function() { 
     if(!!app) { 
      this.svrInit(); 
     } 
    } 
}); 

module.exports = User; 

И я хочу добавить функции на позвоночнике с помощью моего «app_model.js» файл, который выглядит примерно так себе:

var Backbone = require('backbone'), 
    Deferred = require('Deferred'), 
    when = Deferred.when; 

Backbone.Model.prototype.svrInit = function() { 
    //TODO: perhaps the code below should be made static some how so we don't have a bunch of instances of collection 
    var model = this; 
    if(!!app.db){ 
     app.db.collection(this.name,function(err,collection){ 
      model.collection = collection; 
     }); 
    } 
}; 

Backbone.Model.prototype.svrSave = function() { 
    var model = this.toJSON(); 
    var dfd = new Deferred(); 
    this.collection.insert(model, {safe:true}, function(err, result){ 
     dfd.resolve(); 
    }); 
    return dfd; 
}; 

Backbone.Model.prototype.svrFind = function(options) { 
    var model = this.toJSON(); 
    var dfd = new Deferred(); 
    this.collection.find(options, {safe:true}, function(err, result){ 
     dfd.resolve(); 
    }); 
    return dfd; 
}; 

module.exports = Backbone; 

Я проверил свои тесты, когда я отвлек это и, похоже, все в порядке. Есть ли лучший способ сделать это? Любая яма падает? Я использую глобальную переменную «app», это плохо? Если да, то каковы некоторые из них? Я нахожу это уродливым, что мне пришлось поставить this.svrInit() внутри функции init на уровне модели, так или иначе, чтобы автоматически сделать это после создания?

ответ

5

Так я думал над этим вопросом в течение нескольких дней, и я чистейшая вещь, которую я придумал что-то вроде этого:

var MyModel = function(attributes, options) { 
    Backbone.Model.apply(this, arguments); 
    this.specialInitializer(); 
}; 

MyModel.extend = Backbone.Model.extend; 

_.extend(MyModel.prototype, Backbone.Model.prototype, { 
    specialInitializer: function() { 
    // called after the users 'initialize' 
    console.log("MyModel initialized.", this); 
    }, 
    otherNewMethod: function() { 
    // this is just like any other instance method, 
    // just as if Backbone.Model implemented it 
    } 
}); 

Так что это делает в основном делает совершенно новым «вид» Backbone.Model. Один из них также вызывает specialInitializer. Если вы посмотрите на backbone source сразу после определения конструктора для Backbone.Model, вы увидите, что это аналогичная стратегия.

  • Построить экземпляр.
  • Вызовите инициализатор, который должен определить разработчик.
  • Расширьте прототип с функциональностью (в их случае Backbone.Events, наш, Backbone.Model).

Ваш новый инициализатор может, конечно, вызов, что еще ему нужно, и т.д.

Что касается других ваших вопросов о статической вещи коллекции и глобальной переменной приложения, я боюсь, что я не следовать точно, что происходит там, так как я не вижу определения для app и не знаю, для чего вы используете коллекцию.

Вот a fiddle, который демонстрирует это с помощью некоторых дополнительных протоколов и т. Д.

+0

Ааа, я вижу! Я видел несколько подобных концепций, плавающих вокруг, но не был уверен, как это было достигнуто. Часть моего вопроса была о Node.JS. У меня есть файл server.js, который определяет переменную app с помощью expressjs. Он является глобальным и доступен через часть моего приложения на стороне сервера. Все примеры, которые я видел, делают это.Думаю, я мог бы подумать об этом как о «окне» или «документе»; однако я создал db-соединение и ввел его в переменную 'app'. В противном случае я буду создавать новые соединения DB для каждой модели. Думаю, это имеет смысл. Однако использование глобальных переменных не рекомендуется ... – Parris

+0

'app.db.collection' - глобальная переменная приложения. db является частью библиотеки NodeJS mongodb. коллекция относится к коллекции mongodb. Если вы не знаете о коллекциях, они в основном похожи на таблицы. Поэтому я заранее планирую нахождение и вставку на них. – Parris

+0

Также мне нравится это решение для вызова функции инициализации! Спасибо за помощь! – Parris

1

Я работаю над довольно большой базой кода с 4-5 уровнями наследования в представлениях. Это шаблон я использую:

var BaseView = Backbone.Model.extend({ 
    somefunc: function() { 
    //contents 
    }, 

    otherfunc: function(a,b,c) { 
    //contents 
    }, 
    //... 
}); 


var User = BaseView.extend({ 
    // things in user view can now access somefunc and otherfunc 
}); 

Вот краткий пример в jsfiddle (обратите внимание, что функция doSearch наследуется)

+1

Да, мы недавно использовали этот шаблон для точки. Мы заметили, что 4-> 5 уровней наследования привели нас в кучу неприятностей. Мы решили, что шаблон mixin был очень полезен в сочетании с некоторым ограниченным количеством наследования. Мы используем: https://github.com/rhysbrettbowen/Backbone.Advice – Parris

Смежные вопросы