Одна из основных проблем для новых программистов, изучающих Meteor.js, заключается в том, как работать с данными, поступающими с сервера MongoDB на клиент, объектно-ориентированным способом. Когда вы впервые начинаете изучать Meteor, не очевидно, как обернуть коллекцию (эквивалент Meteor «модели» в парадигме модель-представление-контроллер) в формат данных, с которым вы можете легко работать.

В стандартной среде MVC, такой как Rails, вам не нужно беспокоиться о создании собственных абстракций для более простой работы с данными, поступающими из серверной части в пользовательский интерфейс. Active Record сделает все за вас в Rails. В Meteor у нас нет эквивалентной встроенной абстракции. Стандартная функциональность Meteor делает слой модели довольно компактным и вместо этого использует простой JavaScript для представления документов MongoDB. Но еще не все потеряно! Ниже я объясню, как вы можете изменить необработанный вывод сервера для клиента с помощью встроенного метода преобразования Meteor.

Во-первых, я хотел бы начать с демонстрации общего способа обработки создания классов в JavaScript. Основная концепция, которую я собираюсь рассмотреть, — это наследование. Поскольку JavaScript — это язык, основанный на прототипах (в отличие от Ruby или Java, которые основаны на классах), в нем нет понятия классов как таковых. Мы можем объявить класс так же, как и функцию:

function Teletubby() {};

Правильное имя для этого классоподобного объекта в JavaScript — конструктор. Чтобы изменить свойства конструктора, вы должны сделать это через свойство конструктора с именем прототип:

function Teletubby() { // new constructor!
}

Teletubby.prototype.sayEhoh = function() {
  return "Eh-oh!";
};

var tinkyWinky = new Teletubby();
var laaLaa = new Teletubby();

tinkyWinky.sayEhoh(); // "Eh-oh!"
laaLaa.sayEhoh(); // "Eh-oh!"

Теперь мы можем успешно создавать экземпляры новых телепузиков и заставлять их говорить Э-э-э! семантически значимым образом. Мы также можем перезаписать унаследованный метод sayEhoh() для каждого экземпляра нового объекта Teletubby, сохраняя при этом наш код чистым и организованным.

Как теперь добиться того же эффекта, работая в Meteor? Ответ таков: используя преобразование для добавления вычисляемых свойств, с которыми мы можем работать на стороне клиента, в наш объект Collection.

Во-первых, давайте создадим коллекцию для работы с:

lib/collections/teletubbies.js
Teletubbies = new Mongo.Collection('teletubbies', {
  transform: function(doc) {
      return ( new Teletubby( doc ) );
}
});

Теперь давайте опубликуем коллекцию клиенту через публикацию:

server/publications/publications.js
Meteor.publish(‘teletubbies’ , function() {
 return ( Teletubbies.find() );
});

На клиенте Meteor предоставляет нам мини-базу данных Minimongo, которая принимает данные Collection с сервера по подписке (используя Meteor.subscribe):

lib/collections/teletubbies.js
if (Meteor.isClient) {
 Meteor.subscribe(‘teletubbies’);
}

Теперь давайте сразу приступим к трансформации. Вот объяснение этого свойства в документации Meteor:

Теперь мы можем добавить метод в нашу коллекцию через прототип следующим образом:

// doc is documents data coming from MongoDB
Teletubby = function (doc) {
   _.extend(this, doc);
};
_.extend(Teletubby.prototype, {   
  sayEhoh: function () {    
   return "Eh-oh!";   
  }
});

Обратите внимание, что новый Mongo.Collection не создает новую таблицу в базе данных MongoDB. Вместо этого он создает объект, представляющий вашу коллекцию MongoDB (которая может уже существовать, а может и не существовать). Фактическая коллекция создается, когда вы вставляете такой объект документа в консоль браузера:

Teletubbies.insert({name: "tinkyWinky"});
Teletubbies.insert({name: "laaLaa"});

Теперь мы можем найти коллекцию на клиенте и вызвать для нее созданный нами метод:

Teletubbies.findOne({name: "tinkyWinky"}).sayEhoh(); // "Eh-oh!"
Teletubbies.findOne({name: "laaLaa"}).sayEhoh(); // "Eh-oh!"

Вот как это выглядит в консоли:

Насколько мне известно, преобразование до сих пор не является распространенным способом манипулирования данными в приложениях Meteor. Хотя он недостаточно представлен, я думаю, что это отличный инструмент, который может помочь сделать ваш код более удобным для сопровождения и организованным в долгосрочной перспективе. Каково ваше мнение о трансформации? Это обычно используется в производстве или в настоящее время является новинкой?

Обратная связь очень ценится!