Comparing version 0.0.2 to 0.0.3
@@ -131,3 +131,3 @@ FAQ for Derby 0.6 | ||
}); | ||
} | ||
}); | ||
@@ -243,5 +243,4 @@ // Derby renders on both client and server, and does some sneaky little tricks | ||
Comp.prototype.init = function(){ | ||
var count = this.model.at('count'); | ||
// count.path() returns something like: $components._1.count | ||
this.model.root.start(count.path(), 'items', function(items){ | ||
// istead of path we can use scope, and scope always takes data from the root | ||
this.model.start('count', this.model.scope('items'), function(items){ | ||
return Object.keys(items).length; | ||
@@ -248,0 +247,0 @@ }); |
{ | ||
"name": "derby-faq", | ||
"version": "0.0.2", | ||
"version": "0.0.3", | ||
"description": "Derby 0.6 FAQ", | ||
@@ -5,0 +5,0 @@ "scripts": { |
213
ru/README.md
@@ -100,3 +100,3 @@ FAQ по Derby 0.6 (на русском) | ||
}); | ||
} | ||
}); | ||
@@ -138,3 +138,103 @@ // Реактивные функции необходимо регистрировать после того, | ||
``` | ||
--- | ||
#### Можно ли в derby делать distinct запросы к базе mongodb | ||
Да, пример: | ||
```js | ||
// В коллекции items отбираем элементы с типом: public | ||
// и получаем все уникальные имена | ||
var query = model.query('items', { | ||
$distinct: true, | ||
$field: 'name', | ||
$query: { | ||
type: 'public' | ||
} | ||
}) | ||
model.subscribe(query, function(){ | ||
query.refExtra('_page.uniqueNames'); | ||
}); | ||
``` | ||
--- | ||
#### Можно ли в derby делать mapReduce запросы к базе mongodb | ||
Да, но предварительно эту возможность нужно включить на сервере: | ||
```js | ||
var liveDbMongo = require('livedb-mongo'); | ||
var derby = require('derby'); | ||
var store = derby.createStore({ | ||
db: liveDbMongo(process.env.MONGO_URL + '?auto_reconnect', { | ||
safe: true, | ||
allowJSQueries: true // Вот здесь | ||
}), | ||
redis: redisClient | ||
}); | ||
``` | ||
Далее: | ||
```js | ||
// Требования к функциям map и reduce полностью согласуются | ||
// с документацией mongo | ||
var query = model.query('items', { | ||
$mapReduce: true, | ||
$map: function(){ | ||
emit this.player, this.score | ||
}, | ||
$reduce: function(key, values){ | ||
values.reduce(function(a, b) { | ||
return a + b; | ||
}); | ||
}, | ||
$query: { | ||
type: 'public' | ||
} | ||
}) | ||
model.subscribe(query, function(){ | ||
query.refExtra('_page.scores'); | ||
}); | ||
``` | ||
--- | ||
#### Можно ли в derby делать aggregate запросы к базе mongodb | ||
Да, но предварительно эту возможность нужно включить на сервере: | ||
```js | ||
var liveDbMongo = require('livedb-mongo'); | ||
var derby = require('derby'); | ||
var store = derby.createStore({ | ||
db: liveDbMongo(process.env.MONGO_URL + '?auto_reconnect', { | ||
safe: true, | ||
allowAggregateQueries: true // Вот здесь | ||
}), | ||
redis: redisClient | ||
}); | ||
``` | ||
Далее: | ||
```js | ||
// Внутри aggregate запрос абсолютно соответствует документации | ||
// к mongoDb | ||
var query = model.query('items', { | ||
$aggregate: [{ | ||
$group: { | ||
_id: '$y', | ||
count: {$sum: 1} | ||
} | ||
}, { | ||
$sort: {count: 1} | ||
}] | ||
}) | ||
model.subscribe(query, function(){ | ||
query.refExtra('_page.results'); | ||
}); | ||
``` | ||
--- | ||
## Компоненты | ||
@@ -225,5 +325,5 @@ | ||
Comp.prototype.init = function(){ | ||
var count = this.model.at('count'); | ||
// count.path() возращает что-то типа: $components._1.count | ||
this.model.root.start(count.path(), 'items', function(items){ | ||
// вместо пути можно передавать scope, а scope берет items из корня - #root.items | ||
this.model.start('count', this.model.scope('items'), function(items){ | ||
return Object.keys(items).length; | ||
@@ -235,2 +335,76 @@ }); | ||
--- | ||
#### Как лучше всего подписываться на события модели в компонентах? | ||
Если делать `on` и `once` используя обычную модель, то необходимо будет отписывать при `destroy` компонента. | ||
```javascript | ||
MyComponent.prototype.init = function(model){ | ||
var this.handler = model.root.on('change', 'chats.*', function(){ | ||
}); | ||
} | ||
MyComponent.prototype.destroy = function(){ | ||
this.model.removeListener(this.handler); | ||
} | ||
``` | ||
Если делать подписку через scoped-модель, компонента при уничтожении сама позаботиться о подписках: | ||
```javascript | ||
MyComponent.prototype.init = function(model){ | ||
model.scope('chats').on('change', function(){ | ||
}); | ||
} | ||
``` | ||
--- | ||
#### Есть ли возможность давая псевдонимы компонентам через as вынести их в единую глобальную область видимости? | ||
Да, это можно сделать вкладывая их в `page` | ||
Допустим у нас есть компонетны A, B и С | ||
```js | ||
app.component('a', A); | ||
app.component('b', B); | ||
app.component('c', C); | ||
function A(){}; | ||
function B(){}; | ||
function C(){}; | ||
``` | ||
index.html | ||
```html | ||
<Body:> | ||
<view name="a" as="page.a"/> | ||
<a:> | ||
<view name="b" as="page.b"/> | ||
It's A | ||
<b:> | ||
<view name="c" as="page.c"/> | ||
It's B | ||
<c:> | ||
It's C | ||
``` | ||
Теперь в коде любой из компонет A, B или С доступны все эти 3 комопненты, несмотря на иерархию. | ||
```js | ||
A.prototype.show = function(){ | ||
// ... | ||
}; | ||
C.prototype.onClick = function(){ | ||
this.page.A.show(); // Самое важное здесь | ||
}; | ||
``` | ||
Поятно, что если бы именование производилось не через 'page', то в компоненте A была бы доступна только компонента B, а в B - компонента С. | ||
--- | ||
## Модель | ||
@@ -265,2 +439,33 @@ | ||
--- | ||
#### Что такое model.context и как его использовать? | ||
Перставим себе такую ситуацию. В приложении на странице у нас есть список чатов и окошко с выбраным чатом. Если в спике выбрать какой-то определенный чат и кликнуть по нему - в окошке с чатом, без перезагрузки страницы (без смены url) - должен загрузиться выбранный чат. То-есть за сценой должно произойти следующее: нужно отписаться от всех подписок на данные, на которые окошко с чатом было подписано, выгрузить эти данные, и подписаться на новые. В общем случае, подписок может быть достаточно много и управлением ими могло бы превратиться в достаточно сложную задачу, но здесь нам поможет `model.context`. Он создан для решения как раз этой задачи. С его помощью мы можем, создавая подписки, привязывать их к определенному пространству имен. Когда же нам понадобиться отписаться от всего разом - мы сможем просто указать, какое пространство имен выгрузить. | ||
Схематично, как это будет работать в компоненте чата: | ||
```js | ||
// Компонент чата подписывается на данные | ||
var model = this.model.context('chat'); | ||
// Переменная model - это обычная модель компоненты, | ||
// только находящаяся в контексте "chat" | ||
var messagesQuery = model.query('messages', { | ||
// .. | ||
}); | ||
// Подписка делается в контексте | ||
model.subscribe('messagesQuery', function(){ | ||
// ... | ||
}); | ||
``` | ||
Теперь посмотрим как отписаться разом от всех подписок контекста chat и выгрузить все данные: | ||
```js | ||
var model = this.model.context('chat'); | ||
model.unload(); | ||
``` | ||
--- | ||
## База данных | ||
@@ -267,0 +472,0 @@ |
71552