You are on page 1of 261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

http://pt.discovermeteor.com/pdf

1/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

DISCOVERMETEOR
BuildingRealTimeJavaScriptWebApps

TomColeman&SachaGreif

Cover photo credit

Perseid Hunting by Darren Blackburn

Commons Attribution

2.0

licensed under a Creative

Generic license

www discovermeteor com

http://pt.discovermeteor.com/pdf

2/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Introduo

Faa um pequeno experimento mental para mim

Imagine que voc

est abrindo uma pasta

em duas diferentes janelas do seu computador

Agora clique dentro de uma das janelas e delete um arquivo

outra janela tamb

Voc

Esse arquivo desapareceu da

no precisa realmente seguir esses passos para saber disso

algo num sistema de arquivos local

refreshes ou callbacks

Entretanto

a mudana

Quando n

s modificamos

aplicada em todo lugar sem necessidade de

Apenas acontece

vamos pensar sobre como o mesmo cenrio funcionaria na web

vamos dizer que voc

abriu o mesmo site do Wordpress como admin em duas janelas do

browser e ento criou um nova postagem numa delas

quanto voc

espere

s nos acostumamos com a id

se comunica apenas com pequenos

Mas Meteor

Ao contrrio do desktop

a outra janela no vai refletir a mudana a no ser que voc

Ao longo dos anos

Por exemplo

no importa o

a atualize

ia de um website ser algo com o qual voc

separados acessos

parte de uma nova onda de frameworks e tecnologias que esto procurando

desafiar o status quo ao fazer a web em tempo real e reativa

Oquemeteor?

Meteor

uma plataforma constru da em cima de Node js para a construo de web apps em

tempo real

o que fica entre o banco de dados do seu app e a interface do usurio e garante

que ambos mantenham sincronia

J que

. ,

constru do sobre Node js

O melhor

que Meteor tamb

O resultado disso tudo

http://pt.discovermeteor.com/pdf

Meteor usa JavaScript tanto no cliente quanto no servidor

m consegue compartilhar c

digo entre ambos ambientes

uma plataforma que consegue ser muito poderosa e muito simples

3/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

abstraindo muitos dos aborrecimentos e armadilhas comuns ao desenvolvimento de

aplicativos web

PorqueMeteor?

Ento por que voc

framework

deveria investir seu tempo aprendendo Meteor ao inv

Deixando de lado todas as caracter sticas do Meteor

resume a uma

nica coisa

Meteor

E se voc

j fez desenvolvimento front end

j est familiarizado com JavaScript e no ser necessrio nem aprender uma

nova linguagem

.
,

Meteor pode ser o framework ideal para suas necessidades

ser

s acreditamos que tudo se

Meteor torna poss vel criar um web app em tempo

real e funcionando na web em questo de horas

voc

fcil de aprender

Mais do que qualquer outro framework

antes

s de um outro web

Mas j que voc

ou ento novamente pode no

pode se familiarizar ao longo de algumas noites or um fim de semana

por

que no tentar e descobrir por si mesmo

Porqueestelivro?

Ao longos dos

ltimos

meses

s estivemos trabalhando em Telescope

Meteor open source que permite qualquer um criar sua pr

),

em Reddit ou Hacker news

pria rede social de not cias

pense

onde pessoas podem enviar links e votar neles

um aplicativo

s aprendemos um bocado construindo esse aplicativo

mas no era sempre fcil encontrar

as respostas para as quest

em muitos casos at

es

s tivemos de encaixar as peas de muitas fontes diferentes

inventar nossas pr

de compartilhar todas essas li

es

prias solu

.
es

Ento com este livro

--

s gostar amos

e criar um simples guia passo a passo que o guiar atrav

da construo de um aplicativo em Meteor completo do zero

O aplicativo que n

Telescope

s estamos construindo

uma verso ligeiramente simplificada do

o qual chamamos de Microscope

Enquanto o construimos

iremos ver todos os

diferentes elementos necessrios na construo de um aplicativo em Meteor

de usurios

cole

es Meteor

http://pt.discovermeteor.com/pdf

roteamento

e mais

tais como contas

.
4/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

E ap

s voc

ter terminado o livro

digo do Telescope

se voc

quiser ir adiante voc

poder facilmente entender o

j que segue os mesmos padr

es

SobreosAutores

Caso voc

esteja se perguntando quem somos n

segue um pouco sobre a experi

Tom Coleman

ncia do usurio

Meteor

rio de pacotes

s e porque voc

).

deveria confiar em n

aqui

.
,

uma loja de web development com foco em

Ele tamb

e est tamb

s dois

uma parte do Percolate Studio

qualidade e experi

reposit

ncia de n

co autor do Meteorite e da Atmosphere

m por trs de muitos outros projetos open source em

tais como o Router

Sacha Greif tem trabalhado com startups tais como Hipmunk e RubyMotion na rea de

design de produto e web

),

Telescope

e tamb

Ele tamb

criador do Telescope e Sidebar

o qual

baseado em

fundador do Folyo

CaptuloseBarrasLaterais

s queremos que este livro seja

programadores avanados

regulares

numeradores de

til tanto para novatos em Meteor quanto para

ento n

1 14
a

e barras laterais

Cap tulos regulares lhe guiaro atrav

s dividimos os cap tulos em duas categorias

(.5

).

cap tulos

meros

s da construo do aplicativo

e tentaro te deixar o

mais operacional o mais cedo poss vel explicando os mais importantes passos sem lhe

aborrecer com detalhes demais

Por outro lado

barras laterais iro mais aprofundadamente nas entranhas do Meteor

e o

ajudaro a ter uma compreenso melhor do que realmente est acontecendo por trs das

cortinas

Ento se voc

leitura

um iniciante

sinta se livre para ignorar as barras laterais na sua primeira

e volte a elas mais tarde quando voc

http://pt.discovermeteor.com/pdf

j tiver experimentado Meteor

5/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

CommitseLiveInstances

No h nada pior do que seguir um livro de programao e de repente perceber que o seu

digo est fora de sincronia com os exemplos e que nada mais funciona como deveria

Para evitar isto

,
n

s estabelecemos um reposit

rio GitHub para o Microscope

providenciaremos links para os git commits a cada algumas mudanas de c

Adicionalmente

cada commit tamb

commit em particular

ento voc

e n

s tamb

digo

m linka para uma live instance do aplicativo nesse

pode compar la a sua c

pia local

Aqui est um exemplo

de como isso se parecer

Commit112

Display notifications in the header

Ver no GitHub

Lanar Instncia

Mas perceba que apesar de provermos esses commits isso no significa que voc

ir de um

git checkout

ao pr

ximo

Voc

tempo para digitar manualmente o c

aprender muito melhor se voc

deva apenas

aproveitar o

digo do seu aplicativo

AlgunsOutrosRecursos

Se voc

quiser aprender mais sobre um aspecto em particular do Meteor

oficial do Meteor

o melhor lugar para comear

s tamb

a documentao

m recomendamos Stack Overflow para exposio de problemas e perguntas

meteor IRC channel se voc

http://pt.discovermeteor.com/pdf

precisar de aux lio em tempo real

e o

6/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

EuprecisodeGit?
Apesar de estar familiarizado com o Git version control no

para seguir ao longo deste livro

s recomendamos muito

estritamente necessrio

Se voc

quiser um comeo veloz

s recomendamos Nick Farina s Git Is Simpler

Than You Think

Se voc

Mac

um novato em Git

o qual permite a voc

de comando

s tamb

m recomendamos o aplicativo GitHub for

clonar e administrar reposit

rios sem precisar usar a linha

EntrandoemContato

Se voc

hello

quiser entrar em contato conosco

discovermeteor com

Adicionalmente

se voc

voc

pode nos enviar um email para

encontrar um typo ou outro erro no conte

pode nos avisar submetendo um erro neste reposit

Se voc

rio GitHub

tiver um problema com o c

no reposit

Finalmente

digo do Microscope

voc

do do livro

voc

pode submeter um error

rio do Microscope

para qualquer outra questo voc

comentrio para n

http://pt.discovermeteor.com/pdf

tamb

s na barra lateral deste aplicativo

m pode apenas deixar um

7/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

ComeandocomMeteor

Primeiras impress

es so importantes

relativamente indolor

e o processo de instalar o Meteor deve ser

Na maioria dos casos

voc

estar em desenvolvimento em menos de

minutos

Para comear

,
n

s podemos instalar o Meteor abrindo a janela do terminal e teclando

$ curl https://install.meteor.com | sh

Isto instalar o executvel

No

meteor

no seu sistema pronto para voc

usar Meteor

InstalandoMeteor

Se voc

no pode

ou no quer

instalar Meteor localmente

s recomendamos

checar Nitrous io

Nitrous io

um servio que permite a voc

mesmos direto no seu navegador

e n

rodar aplicativos e editar o c

digo dos

s escrevemos um pequeno guia para ajud lo

a comear

Voc

pode simplesmente seguir o guia at

Meteor

&

Meteorite

segmento

e incluindo

o segmento

Instalando

e ento seguir junto com o livro novamente comeando do

Criando um Simples Aplicativo

deste cap tulo

Meteorite

Devido ao fato que Meteor no suporta pacotes de terceiros diretamente

dos autores do livro

Meteor

Tom Coleman

e alguns membros da comunidade criaram Meteorite

Meteorite tamb

m toma conta da instalao de Meteor para voc

qualquer pacote que voc

http://pt.discovermeteor.com/pdf

encontrar

um inv

um

lucro para

e juntando a ele

.
8/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

J que n

s necessitaremos de pacotes de terceiros para algumas das funcionalidades do

Microscope

vamos instalar Meteorite

InstalandoMeteorite

Voc

precisar se assegurar que node e git estejam instalados na sua mquina

forma padro para o seu Sistema Operacional

Instale os da

ou tente os links a seguir

Node download site

Git download site

Segundo

vamos instalar Meteorite

formato padro de m

Como

),

dulo do Node

um executvel npm

Node Packaged Module

s o instalaremos com

$ npm install -g meteorite

ErrosdePermisso?

Em algunas mquinas voc

Para evitar problemas

pode precisar de root permission para instalar Meteorite

faa questo de usar

sudo -H :

$ sudo -H npm install -g meteorite

Voc

isso a

Nota

pode ler mais sobre esta questo na documentao do Meteorite

Meteorite lidar com as coisas agora

ainda no h suporte Windows para Meteorite

tutorial windows

mas voc

pode dar uma olhada no nosso

http://pt.discovermeteor.com/pdf

9/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

### mrt

meteor

vs

Meteorite instala o executvel

nosso aplicativo

mrt , o qual ns usaremos para instalar pacotes no

Quando n

usaremos o executvel

s quisermos ativar nosso servidor

entretanto

meteor .

CriandoumSimplesAplicativo

Agora que n

s temos o Meteorite instalado

vamos criar um aplicativo

usamos a ferramenta da linha de comando do Meteorite

Para fazer isto

,
n

mrt :

$ mrt create microscope

Este comando carregar o Meteor

voc

usar

Ap

s isto

voc

e estabelecer um projeto Meteor bsico e pronto para

, microscope/ ,

poder ver um diret

rio

contendo o seguinte

microscope.css
microscope.html
microscope.js
smart.json

O aplicativo que o Meteor criou para voc

padr

um simples aplicativo clich

demonstrando alguns

es simples

Apesar do nosso aplicativo no fazer muito

s j podemos rod lo

Para rod lo

v at

terminal e digite

$ cd microscope
$ meteor

http://pt.discovermeteor.com/pdf

10/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Agora navegue no seu navegador para

http://0.0.0.0:3000/

e voc

http://localhost:3000/

ou o equivalente

dever ver algo assim

MeteorsHelloWorld.

Commit21

Created basic microscope project

Ver no GitHub

Parab

ns

Voc

conseguiu rodar seu primeiro aplicativo em Meteor

aplicativo tudo o que voc

rodando

Lanar Instncia

e pressionar

precisa fazer

Alis

para desativar seu

abrir a janela do terminal onde o aplicativo est

ctrl+c .

AdicionandoumPacote

s agora usaremos Meteorite para adicionar um pacote inteligente que nos permitir incluir

Bootstrap no nosso projeto

http://pt.discovermeteor.com/pdf

11/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

$ mrt add bootstrap

Commit22

Added bootstrap package

Ver no GitHub

Lanar Instncia

UmanotasobrePacotes

Quando se fala de pacotes no contexto de Meteor

usa cinco tipos bsicos de pacotes

O n

cleo do Meteor em si

deve se ser espec fico

precisar se preocupar com eles

e voc

pode ver a lista completa com

Voc

meteor list

37

pacotes

que v

quando voc

voc

m embrulhados com

pode opcionalmente importar para o seu pr

pode adicion los at

Eles

em geral quase nunca

Os pacotes inteligentes do Meteor so um grupo de uns

O Meteor

dividido em diferentes pacotes nucleares

esto inclusos em cada aplicativo em Meteor

Meteor e que voc

prio aplicativo

no est usando Meteorite

com

meteor add packagename .

Pacotes locais so pacotes customizados que voc


diret

rio

pode criar e por no

/packages . Voc tambm no precisa usar Meteorite para us

los

Pacotes inteligentes da Atmosphere so pacotes Meteor de terceiros listados

em Atmosphere

Pacotes NPM

Meteorite

necessrio para importar e us los

Node Packaged Modules

. .

so pacotes do Node js

no funcionarem diretamente com Meteor

de pacote pr

Atmosphere

Apesar deles

eles podem ser usados pelos tipos

vios

AEstruturadeArquivosdeumAplicativoemMeteor

Antes de n

s comearmos a programar

http://pt.discovermeteor.com/pdf

s precisamos estabelecer nosso projeto

12/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

apropriadamente

microscope

A seguir

Para assegurar que n

s tenhamos uma construo limpa

/microscope : /client , /server , /public ,

rios ra z dentro de

/lib , e /collections , e ns tambm criaremos arquivos main.html

Meteor tem algumas regras

rios so especiais

/server

roda apenas no servidor

/client

roda apenas no cliente

digo no diret

digo no diret

rio

rio

/lib

Qualquer arquivo

main.* lido aps todo resto.

fonts

images

Note que apesar do Meteor ter regras

etc

vo no diret

apenas a nossa forma de fazer as coisas

s encorajamos que voc

/public .

rio

ele realmente no fora voc

de arquivos predefinida para o seu aplicativo se voc

so lidos antes dos outros

Seus recursos estticos

Todo resto roda tanto no cliente quanto no servidor

Arquivos no

Em relao a arquivos

sugerimos

vazios

main.js

ximo cap tulo

s devemos mencionar que alguns desses diret

/client . No se preocupe se isso quebrar o aplicativo por enquanto, ns

comearemos a preencher esses arquivos no pr

rio

microscope.html , microscope.js , e microscope.css .

e delete

crie cinco diret

dentro de

abra o diret

no quiser

a usar nenhuma estrutura

Ento a estrutura que n

no uma regra absoluta

cheque a documentao oficial do Meteor se voc

quiser mais

detalhes sobre isso

http://pt.discovermeteor.com/pdf

13/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

OMeteorMVC?

Se voc

est vindo para o Meteor de outros frameworks tais como Ruby on Rails

talvez voc

esteja se perguntando se aplicativos em Meteor adotam o padro MVC

).

Model View Controller

A resposta curta

no

Ao inv

s de Rails

predefinida para o seu aplicativo

Meteor no imp

digo de uma forma que faa mais sentido para n

acr

nimos

Ento neste livro n

e nenhuma estrutura

s simplesmente deixaremos o

sem se preocupar demais com

Nopblico?

OK

s mentimos

s no realmente precisamos do diret

de que o Microscope no usa recursos estticos

public/

rio

pela simples razo

Mas j que a maioria dos aplicativos em

Meteor iro incluir pelo menos um conjunto de imagens

,
n

s pensamos que seria importante

cobrir esse assunto

Alis

voc

pode tamb

guarda seu pr

voc

prio c

m ter notado um diret

digo

rio

.meteor

e modificar coisas aqui

nunca realmente precisar olhar este diret

.meteor/packages

rio

es do Meteor

pode ser

http://pt.discovermeteor.com/pdf

Aqui

geralmente um id

As

nicas excess

onde o Meteor

ia muito ruim

Alis

es a isto so os arquivos

.meteor/release , os quais costumam respectivamente listar seus

pacotes inteligentes e a verso do Meteor a se usar

vers

escondido

Quando voc

adicionar pacotes e mudar

til checar as mudanas a esses arquivos

14/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

UnderscoresvsCamelCase
A

nica coisa que n

vs camelCase

que voc

( myVariable )

que realmente no importa qual voc

( my_variable )
escolha desde

permanea nele

Neste livro

s usaremos camelCase porque

fazer as coisas

As

s iremos dizer sobre o antigo debate underscore

nicas exce

underscores

at

mesmo por que

a forma JavaScript comum de ser

JavaScript e no java

es a esta regra so os nomes de arquivos

( my_file.js ),

razo para tanto

os quais usaremos

as quais usam h fens

pria sintaxe CSS j usa h fens

!).

script

e classes em CSS

que no sistema de arquivos

enquanto a pr

( .my-class ).

underscores so o mais comum

,
.

( font-family , text-align , )
etc

CuidandodasCSS

Este livro no

sobre CSS

Ento para evitar retard los com detalhes de estilizao

decidimos disponibilizar a stylesheet desde o comeo

preocupar com isto de novo

para que voc

jamais precise se

.
,

As CSS so lidas e minificadas automaticamente pelo Meteor

ento diferentemente de outros

/client , no no /public . V em frente e crie um diretrio

recursos estticos elas vo no

client/stylesheets/

agora

e ponha este arquivo

style.css

dentro dele

.grid-block, .main, .post, .comments li, .comment-form {


background: #fff;
border-radius: 3px;
padding: 10px;
margin-bottom: 10px;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15);
}
body {
background: #eee;
color: #666666;
}
.navbar { margin-bottom: 10px }
.navbar .navbar-inner {
border-radius: 0px 0px 3px 3px;
http://pt.discovermeteor.com/pdf

15/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

}
#spinner { height: 300px }
.post {
*zoom: 1;
-webkit-transition: all 300ms 0ms;
-webkit-transition-delay: ease-in;
-moz-transition: all 300ms 0ms ease-in;
-o-transition: all 300ms 0ms ease-in;
transition: all 300ms 0ms ease-in;
position: relative;
opacity: 1;
}
.post:before, .post:after {
content: "";
display: table;
}
.post:after { clear: both }
.post.invisible { opacity: 0 }
.post .upvote {
display: block;
margin: 7px 12px 0 0;
float: left;
}
.post .post-content { float: left }
.post .post-content h3 {
margin: 0;
line-height: 1.4;
font-size: 18px;
}
.post .post-content h3 a {
display: inline-block;
margin-right: 5px;
}
.post .post-content h3 span {
font-weight: normal;
font-size: 14px;
display: inline-block;
color: #aaaaaa;
}
.post .post-content p { margin: 0 }
.post .discuss {
display: block;
float: right;
margin-top: 7px;
}
.comments {
list-style-type: none;
margin: 0;
}
.comments li h4 {
font-size: 16px;
http://pt.discovermeteor.com/pdf

16/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

margin: 0;
}
.comments li h4 .date {
font-size: 12px;
font-weight: normal;
}
.comments li h4 a { font-size: 12px }
.comments li p:last-child { margin-bottom: 0 }
.dropdown-menu span {
display: block;
padding: 3px 20px;
clear: both;
line-height: 20px;
color: #bbb;
white-space: nowrap;
}
.load-more {
display: block;
border-radius: 3px;
background: rgba(0, 0, 0, 0.05);
text-align: center;
height: 60px;
line-height: 60px;
margin-bottom: 10px;
}
.load-more:hover {
text-decoration: none;
background: rgba(0, 0, 0, 0.1);
}

client stylesheets style css

Commit23

Re arranged file structure

Ver no GitHub

http://pt.discovermeteor.com/pdf

Lanar Instncia

17/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

UmanotasobreCoffeeScript

Neste livro n

Meteor te d cobertura

seguir

s iremos escrever em puro JavaScript

Mas se voc

preferir CoffeeScript

Apenas adicione o pacote CoffeeScript e est pronto para

mrt add coffeescript

http://pt.discovermeteor.com/pdf

18/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Deployment

2.5

SIDEBAR

Algumas pessoas gostam de trabalhar quietas num projeto at

ficar perfeito

no conseguem esperar para mostrar ao mundo o mais cedo poss vel

Se voc

enquanto outros

do primeiro tipo de pessoa e prefere desenvolver localmente por hora

de pular este cap tulo

Por outro lado

se voc

sinta se livre

prefere investir seu tempo aprendendo como

implementar seu aplicativo em Meteor na web

s te damos cobertura

s aprenderemos como implementar um aplicativo em Meteor de diferentes formas

livre para usar cada uma delas em qualquer estgio do seu processo de desenvolvimento

trabalhando no Microscope ou qualquer outro aplicativo em Meteor

Vamos comear

Sinta se

seja

IntroduzindoBarrasLaterais
Este

um cap tulo barra lateral

Barras laterais vo mais afundo em t

sobre Meteor independente do resto do livro

Ento se voc

picos gerais

.
,

prefere continuar construindo Microscope

voc

pode seguramente

pular isto por hora e voltar mais adiante

ImplementandocomMeteor

Implementar com um subdom nio Meteor

opo mais fcil

e a primeira que n

aplicativo em Meteor

Isto pode ser

til para mostrar seu

ou para rapidamente montar um servidor de teste

bem simples

e digite

http://meuaplicativo.meteor.com a

s vamos tentar

aplicativo para outros nos primeiros dias

Implementando em Meteor

vulgo

Apenas abra seu terminal

v ao diret

rio do seu

$ meteor deploy myapp.meteor.com

http://pt.discovermeteor.com/pdf

19/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Claro

voc

que ter que substituir

preferidamente um que ainda no esteja em uso

Meteor pedir a voc

ctrl+c

uma senha

meuaplicativo

Se isso ocorrer

pelo nome do seu aplicativo de escolha

Se o nome escolhido j estiver em uso

simplesmente cancele a operao com

e tente novamente com um nome diferente

Se tudo der certo

ap

s alguns segundos voc

poder acessar seu aplicativo em

http://meuaplicativo.meteor.com .

ProteocomSenha

Por padro

no h restrio para subdom nios Meteor

dom nio de sua escolha

Qualquer um pode usar o nome de

e rescrever qualquer aplicativo existente

Ento voc

ir querer por uma senha para proteger o seu nome de dom nio com a opo

provavelmente

-p , como

abaixo

$ meteor deploy myapp.meteor.com -p

Meteor ir ento pedir a voc

necessria toda vez que voc

Voc

para definir uma senha

e da

em diante esta senha ser sempre

quiser implementar este aplicativo em particular

pode checar a documentao oficial para mais informao sobre essas coisas como

acessar a instncia hospedada do banco de dados diretamente

ou como configurar um

dom nio customizado para o seu aplicativo

ImplementandoemModulus

Modulus

uma

provedores PaaS

tima opo para implementar aplicativos em NodeJS

- --

platform as a service

um dos poucos

que oficialmente suportam Meteor

e j h vrias

pessoas rodando aplicativos Meteor em produo nele

http://pt.discovermeteor.com/pdf

20/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Demeteorizer

Modulus liberou uma ferramenta em open source chamada demeteorizer

converte aplicativos em Meteor em aplicativos em NodeJS padro

Comece por criar uma conta

a qual

Para implementar nosso aplicativo no Modulus

s ento

precisaremos instalar a ferramenta de linha de comando Modulus

$ npm install -g modulus

E ento autentic la com

$ modulus login

s agora criaremos um projeto Modulus

(
):

note que voc

tamb

m pode fazer isso atrav

painel de instrumentos online do Modulus

$ modulus project create

O pr

ximo passo ser criar um banco de dados MongoDB para o nosso aplicativo

podemos criar um banco de dados MongoDB com o pr

prio Modulus

MongoHQ ou com

qualquer outro provedor MongoDB em nuvem

Uma vez criado o banco de dados MongoDB

banco de dados com UI online do Modulus

database

>

),

Administration

http://pt.discovermeteor.com/pdf

,
n

s podemos pegar a

v ao Dashboard

>

MONGO_URL

Databases

>

para o nosso

Select your

ento use o para configurar seu aplicativo assim

21/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

$ modulus env set MONGO_URL "mongodb://<user>:<pass>@mongo.onmodulus.net:270


17/<database_name>"

Agora

hora de implementar seu aplicativo

to simples quanto digitar

$ modulus deploy

s implementamos nosso aplicativo no Modulus com sucesso

Modulus para mais informao sobre como acessar logs

Cheque a documentao do

configurando dom nio customizado

e SSL

MeteorUp

Apesar que novas solu

es na nuvem t

pr

m aparecido a cada dia

prias parcelas de problemas e limita

.
es

Ento at

elas costumam vir com suas

hoje

implementar no seu pr

prio

servidor permanece a melhor forma de por seu aplicativo Meteor em produo

questo

implementar voc

mesmo no

to simples

especialmente se voc

nica

est

procurando por implementao com qualidade de produo

Meteor Up

ou a abreviao

mup outra tentativa de resolver essa questo, com um

utilitrio da linha de comando que toma conta da configurao e implementao para voc

Ento vamos ver como implementar Microscope com Meteor Up

Antes de qualquer coisa

,
n

voc

s precisaremos de um servidor para enviar o conte

recomendamos o Digital Ocean

instncias de graa

o qual comea com

$5

por m

ou AWS

do

o qual prov

rapidamente vai se deparar com problemas de escalar

).

Micro

mas se voc

est procurando apenas experimentar Meteor Up ser o suficiente

Independente do servio que voc

servidor

um login

seguro

normalmente

escolher

root

ou

voc

deve ter tr

s coisas

o endereo de IP do seu

ubuntu , e uma senha. Deixe

as em algum lugar

s precisaremos delas logo

http://pt.discovermeteor.com/pdf

22/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

IniciandoMeteorUp

Para comear

,
n

s precisaremos instalar Meteor Up via

npm

como a seguir

$ npm install -g mup

s ento criaremos um diret

rio especial

separado que ter as configura

Meteor Up para uma implementao em particular

separado por duas raz

rep

sitorio Git

Segundo

es

primeiro

especialmente se voc

usando m

s estamos usando um diret

rio

digos p

blico

rios separados

est trabalhando num banco de c

es Meteor Up em paralelo

instncias de produo e teste

es do nosso

melhor evitar incluir credenciais privadas no seu

ltiplos diret

ltiplas configura

s seremos capazes de administrar

Isso ser

til para implementao para

por exemplo

Ento vamos criar este novo diret

rio e us lo para iniciar um novo projeto Meteor Up

$ mkdir ~/microscope-deploy
$ cd ~/microscope-deploy
$ mup init

CompartilhandocomDropbox

Uma grande forma de assegurar que voc

configura

es de implementao

seu Dropbox

e seu time todos esto usando as mesmas

criar uma pasta de configurao do Meteor Up no

ou em qualquer servio similar

ConfiguraodoMeteorUp

Quando comear um novo projeto

: mup.json

Meteor Up criar dois arquivos para voc

settings.json .
http://pt.discovermeteor.com/pdf

23/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

mup.json

ter todas as suas configura

settings.json

tokens

ximo passo

gerado por

es relacionadas ao aplicativo

..

etc

O pr

ter as configura

es relacionadas implementao

enquanto

OAuth tokens

analytics

mup.json . Aqui est um arquivo mup.json

configurar seu arquivo

padro

mup init , e tudo que voc precisa fazer preencher as lacunas:

//server authentication info


"servers": [{
"host": "hostname",
"username": "root",
"password": "password"
//or pem file (ssh based authentication)
//"pem": "~/.ssh/id_rsa"
}],
//install MongoDB in the server
"setupMongo": true,
//location of app (local directory)
"app": "/path/to/the/app",

//configure environmental
"env": {
"ROOT_URL": "http://supersite.com"
}

mup json

Vamos checar cada uma dessas configura

es

Autentificao do Servidor

Voc

perceber que o Meteor Up suporta autenticao baseada em senha e chave privada

( ),
PEM

ento ele pode ser usado com quase qualquer provedor em nuvem

Nota Importante

voc

instalou o

se voc

sshpass

http://pt.discovermeteor.com/pdf

escolher uma autenticao baseada em senha

antes

).

tenha certeza que

use este guia

24/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Configurao MongoDB

O pr

ximo passo

configurar o banco de dados MongoDB para o seu aplicativo

recomendamos usar MongoHQ ou qualquer outro provedor MongoDB em nuvem

j que eles

oferecem suporte profissional e ferramentas administrativas melhores

Se voc

decidir usar MongoHQ

MONGO_URL

ambiental

Meteor Up

no bloco

apenas defina

setupMongo

defina

env

de

setupMongo

como

false

e adicione a varivel

mup.json . Se voc decidir hospedar MongoDB com

como

true

e Meteor Up cuidar do resto

Caminho Meteor Up

J que a nossa configurao do Meteor Up vive em outro diret

rio

o Meteor Up de volta para o nosso aplicativo usando a propriedade

caminho local completo

o qual voc

app . Apenas insira seu

pode conseguir usando o comando

quando localizado dentro do diret

s precisaremos apontar

pwd

pelo terminal

rio do seu aplicativo

Variveis Ambientais

Voc

pode especificar todas as variveis ambientais do seu aplicativo

MAIL_URL , MONGO_URL , etc.

dentro do bloco

env .

tais como

ROOT_URL ,

ConfigurandoeImplementando

Antes de n

s implementarmos

s precisaremos configurar o servidor para que esteja pronto

para hospedar seus aplicativos em Meteor

complexo em um

A mgica do Meteor Up captura este processo

nico comando

$ mup setup

Isto levar alguns minutos dependendo da performance do servidor e da conectividade da

rede

com

Ap

s o sucesso da instalao

s podemos finalmente implementar nosso aplicativo

http://pt.discovermeteor.com/pdf

25/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

$ mup deploy

Isto embrulhar o aplicativo em Meteor

e o implementar no servidor que n

s configuramos

MostrandoLogs

Logs so bem importantes e o Meteor Up prov

uma maneira bem fcil de lidar com eles ao

tail -f . Apenas digite:

emular o comando

$ mup logs -f

Isto resume a viso geral do que o Meteor Up pode fazer

visitar o reposit

rio GitHub do Meteor Up

Para mais informao

,
n

s sugerimos

Estas tr

s maneiras de implementar aplicativos em Meteor deve ser o suficiente para a maioria

dos casos

Claro

,
n

s sabemos que voc

servidor Meteor do princ pio

http://pt.discovermeteor.com/pdf

Mas isto

prefere estar em total controle e configurar seu

um t

pico para outro dia

ou talvez outro livro

26/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Templates

Para facilitar o desenvolvimento em Meteor

dentro

s adotaremos uma abordagem de fora para

Em outras palavras

HTML JavaScript primeiro

s iremos constuir uma casca externa

burra

com

e ento associar com o funcionamento interno de nosso aplicativo

no subsequentes trabalhos

Isto significa que neste cap tulo n

dentro do diret

rio

s apenas nos preocuparemos com o que est acontecendo

client

Vamos criar um novo arquivo chamado main html dentro de nosso diret

preench

lo com o seguinte c

digo

rio

client

e vamos

<head>
<title>Microscope</title>
</head>
<body>
<div class="container">
<header class="navbar">
<div class="navbar-inner">
<a class="brand" href="/">Microscope</a>
</div>
</header>
<div id="main" class="row-fluid">
{{> postsList}}
</div>
</div>
</body>

client main html

Este ser nosso principal template do aplicativo

uma

nica tag

Como voc

pode ver

HTML puro exceto por

{{> postsList}} , a qual um ponto de insero para o template postList

como logo veremos

Por enquanto

vamos criar mais alguns templates

MeteorTemplates

http://pt.discovermeteor.com/pdf

27/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

No seu mago

um site de not cias sociais

composto de postagens organizadas em listas

,
e

exatamente assim que iremos organizar nossos templates

Vamos criar um diret

nossos templates

dentro de

/views

/views

rio

/client . Isto ir ser onde ns colocaremos

dentro de

e para manter as coisas organizadas n

s tamb

/posts

m criaremos

apenas para nossos templates relacionados com postagens

FindingFiles

O Meteor

incr vel para encontrar arquivos

digo no diret

/client , o Meteor ir encontr

rio

Isto significa que voc

No importa onde voc

colocou o seu

lo e compil lo corretamente

nunca precisar manualmente escrever caminhos para

incluso de arquivos JavaScript ou CSS

Isto tamb

m significa que voc

mesmo diret

rio

poderia muito bem colocar todos os seus arquivos no

ou ainda todo o seu c

o Meteor vai compilar tudo em um

digo em um mesmo arquivo

Mas desde que

nico arquivo minificado de qualquer forma

melhor que mantemos as coisas bem organizadas e utilize uma estrutura clara de

arquivos

s finalmente estamos prontos para nosso segundo template

Dentro de

client/views/posts , crie posts_list.html :

<template name="postsList">
<div class="posts">
{{#each posts}}
{{> postItem}}
{{/each}}
</div>
</template>

client views posts posts

list html

post_item.html :

http://pt.discovermeteor.com/pdf

28/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

<template name="postItem">
<div class="post">
<div class="post-content">
<h3><a href="{{url}}">{{title}}</a><span>{{domain}}</span></h3>
</div>
</div>
</template>

/ _

client views posts post

Note o atributo

item html

name="postList"

do elemento template

Este

o norme que ser utilizado

pelo Meteor para acompanhar qual template vai aonde

hora de introduzir o sistema de templating do Meteor

simplesmente HTML

blocos de ajuda

com a adio de tr

).

s coisas

parciais

partials

),

Handlebars

express

es

expressions

block helpers

As parciais usam a s ntaxe

{{> templateName}} , e simplemente dizem ao Meteor para

substituir a parcial com o template de mesmo nome

Express

o Handlebars

es tais como

{{title}}

no nosso caso

postItem .

ou chamam a propriedade do objeto atual

ou retornam o

valor de um auxiliar do template como definido no gerenciador atual do template

).

logo mais

sobre isso

Finalmente

blocos de ajuda so tags especiais que controlam o fluxo do template tais como

{{#each}}...{{\each}}

ou

{{#if}}...{{\if}} .

IndoAlm
Voc

pode visitar o site oficial de Handlebars ou este prtico tutorial se quiser

aprender mais sobre Handlebars

Armado com este conhecimento

aqui

s podemos facilmente entender o que est acontecendo

http://pt.discovermeteor.com/pdf

29/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Primeiro

no template

postsList , ns estamos iterando sobre um objeto posts

com o

{{#each}}...{{\each}} . Ento, para cada iterao ns incluimos o template

bloco de ajuda

postItem .

De onde este objeto

template

e n

title

Boa pergunta

Se trata na verdade de um ajudante do

em si mesmo

bem direto

Apenas usa tr

ambas retornando as propriedades do documento

ajudante do template

se origina

s iremos defini lo quando olharmos para os gerenciadores de template

postItem

O template

{{ }}

posts

s mencionamos

"

s express

{{domain}}

: {{url}}
es

que chama um

ajudantes do template

explicar o que eles fazem

bastante ao longo deste cap tulo sem realmente

Mas para consertar isso

primeiro precisamos falar sobre gerentes

GerentesdeTemplate

At

agora n

s estvamos lidando com Handlebars

algumas tags especiais

ou at

que nada mais

do que HTML acrescido de

Diferentemente de outras linguagens de programao como o PHP

mesmo pginas HTML comuns

),

que podem incluir JavaScript

templates e as l

necessrio um gerente

antes de entregar o prato finalizado ao garom

Em outras palavras

o template

Voc

gerente como um chef de cozinha que pega os ingredientes crus

o Meteor mant

gicas separadas e esses templates no fazem muita coisa por si s

Para fazer com que eles ganhem vida

gerente

m os

pode pensar em um

seus dados

e prepara eles

que o apresenta a voc

.
,

enquanto o papel do template se limita a exibir ou iterar variveis

aquele que faz todo o trabalho pesado atribuindo valores para cada uma dessas

variveis

http://pt.discovermeteor.com/pdf

30/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Gerentes?

Quando n

s perguntarmos por a

chamam esses

e como a sigla

Javascript

no

metade respondeu

aqueles arquivos onde eu coloco meu c

Gerentes no so de fato

gerentes de template

metade respondeu

MVC

a outros desenvolvedores Meteor como eles

e a outra

digo JavaScript

controllers

AAOECMCJ

controllers

pelo menos no no sentido de controllers do

Aqueles Arquivos Onde Eu Coloco Meu C

muito atraente

s acabamos rejeitando as duas op

digo

es

Como ainda precisvamos usar um nome para indicar aquilo a que estvamos nos

referindo

s optamos pelo termo

gerente

como uma alternativa vivel j que no

tinha um significado relacionado a nenhum outro framework web

Para simplifcar as coisas

template

s iremos adotar a mesma conveno de nomes utilizada para o

com exceo da utilizao da extenso

dentro do diret

rio

/client/views/posts

. .
js

Vamos criar o arquivo

posts_list.js

e comear a definir nosso primeiro gerente

var postsData = [
{
title: 'Introducing Telescope',
author: 'Sacha Greif',
url: 'http://sachagreif.com/introducing-telescope/'
},
{
title: 'Meteor',
author: 'Tom Coleman',
url: 'http://meteor.com'
},
{
title: 'The Meteor Book',
author: 'Tom Coleman',
url: 'http://themeteorbook.com'
}
];
Template.postsList.helpers({
posts: postsData
});

client views posts posts

http://pt.discovermeteor.com/pdf

list js

31/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Se voc

fez tudo certo

algo parecido com isso ir aparecer no seu navegador

Nossoprimeirotemplatecomdadosestticos

Commit31

Template de listagem de posts e dados estticos adicionados

Ver no GitHub

s estamos fazendo duas coisas aqui

array

Lanar Instncia

Primeiro estamos colocando alguns dados de teste no

postsData . Esses dados normalmente seriam provenientes de um banco de dados, mas

- (

como ainda no vimos como acess lo

trapaceando

usando alguns dados estticos

Template.myTemplate.helpers()
posts

aguarde at

posts

o pr

ximo cap tulo

s estamos

Depois estamos usando a funo

do Meteor para definir um ajudante de template chamado

que simplesmente nos retornar o array

Definir o ajudante

postsData .

significa que ele agora estar dispon vel para ser usado pelo nosso

template

http://pt.discovermeteor.com/pdf

32/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

<template name="postsList">
<div class="posts">
{{#each posts}}
{{> postItem}}
{{/each}}
</div>
</template>

client views posts posts

list html

Agora ser poss vel que nosso template itere sobre o array

contido dentro dele para o template

postsData

e envie cada objeto

postItem .

Ovalordothis

s iremos criar agora o gerente

post_item.js

Template.postItem.helpers({
domain: function() {
var a = document.createElement('a');
a.href = this.url;
return a.hostname;
}
});

/ _

client views posts post

item js

Commit32

Definio do ajudante

domain

Ver no GitHub

Desse vez o valor do ajudante

pattern

muito mais comum

domain
e mais

no

til

no template

postItem

`.

Lanar Instncia

um array

mas uma funo an

nima

Esse

se comparado aos nossos exemplos com dados de

teste anteriores

http://pt.discovermeteor.com/pdf

33/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Exibindoosdomniosdecadalink.

O ajudante

Javascript

domain

Mas

recebe uma URL e retorna seu dom nio utilizando um pouco da mgica do

pra comear

de onde ela pega essa URL

Para responder a essa pergunta n

O ajudante

{{#each}}

s precisamos voltar ao nosso template

no apenas itera um array mas tamb

posts_list.html .

m atribui o valor do

this

dentro do bloco do objeto iterado

Isso significa que entre as duas tags

{{#each}} , cada post atribudo ao this

sucessivamente e isso tamb

Agora n

m se aplica ao gerente de template

s entendemos o porque do

s usarmos

{{title}}

sabe que isso significa

http://pt.discovermeteor.com/pdf

{{url}}

this.title

this.url

retornar a URL do post atual

dentro do nosso template

( post_item.js ).

this.url

E al

m disso

se

post_item.html , o Meteor

e retorna os valores corretos

34/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

MgicadoJavascript

Embora isso no seja especif co do Meteor

dessa pequena

(a)

,
.

Primeiro

href

a URL do post atual

s estamos criando

ria

como n

).

s j vimos

corresponde ao objeto sob a qual a ao est acontecendo

Por

descrita acima

vazio e armazenando o na mem

Depois colocamos em seu atributo

this

mgica do Javascript

um elemento HTML de ncora

aqui vai uma breve explicao a respeito

ltimo

s aproveitamos o fato de que o elemento

especial chamada

hostname

tem uma a propriedade

para recuperar o nome de dom nio do link sem o

restante da URL

Se voc

seguiu tudo corretamente

navegador

Essa lista

dever estar vendo agora uma lista de posts no seu

composta apenas por dados estticos

vantagem dos recursos real time do Meteor

portanto ela ainda no tira

s iremos mostrar como mudar isso no pr

ximo

cap tulo

RecarregamentoAutomticodeCdigo
Voc

deve ter notado que no precisa nem recarregar a janela do seu navegador

quando altera um arquivo

Isso acontece porque o Meteor rastreia todos os arquivos dentro do diret

rio do seu

projeto e automaticamente d refresh no seu navegador sempre que detecta

mudanas em algum desses arquivos

O recarregamento automtico de c

digo do Meteor

bem esperto

Ele at

preserva o

estado da sua aplicao entre um refresh e outro

http://pt.discovermeteor.com/pdf

35/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

UsandoGit&GitHub

GitHub

verso

tamb

rio social de projetos open source baseado no sistema Git de controle de

e sua funo principal

um reposit

3.5

SIDEBAR

um

tornar fcil compartilhar c

timo instrumento de ensino

rapidamente por algumas maneiras que voc

digo e colaborar em projetos

Nesta barra lateral

Mas

,
n

s vamos passar

pode utilizar o GitHub para acompanhar o

Descubra Meteor

Esta barra lateral sup

e que voc

confortvel com ambos

no est to familiarizado com Git e GitHub

Se voc

j est

sinta se livre para pular este cap tulo

SendoCommitted

O bloco bsico de trabalho de um reposit

rio git

um commit

Voc

pode pensar o commit

como um instantneo do estado do seu banco de c

Ao inv

s de simplesmente dar a voc

o c

instantneos a cada passo do caminho

Por exemplo

isto

o que o

http://pt.discovermeteor.com/pdf

digo em um dado momento no tempo

digo finalizado do Microscope

e voc

s tiramos estes

pode ver todos eles online no GitHub

ltimo commit do cap tulo pr

vio se parece com

36/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

AGitcommitasshownonGitHub.

O que voc

aqui

(
diff

de

difference

as mudanas introduzidas por este commit

do princ pio

ento todo seu conte

do arquivo

post_item.js , em outras palavras

Neste caso

s criamos o arquivo

post_item.js

do est destacado em verde

Vamos comparar com um exemplo de mais adiante no livro

Modifyingcode.

Desta vez

E claro

apenas as linhas modificadas esto destacadas em verde

s vezes voc

no est adicionando ou modificando linhas de c

digo

mas deletando

as

http://pt.discovermeteor.com/pdf

37/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Deletingcode.

Ento n

s vimos o primeiro uso do GitHub

ver o que mudou num relance

ProcurandoumCdigodeCommit

A vista commit do Git nos mostra as mudanas inclu das neste commit

pode querer ver arquivos que no foram modificados

mas s vezes voc

apenas para ter certeza de como seus

digos devem se parecer neste estgio do processo

Mais uma vez o GitHub vem a n

.
s

Quando voc

est numa pgina commit

clique no boto

Browse code

http://pt.discovermeteor.com/pdf

38/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

TheBrowsecodebutton.

Voc

agora ter acesso ao repo como ele est num commit espec fico

Therepositoryatcommit32.

GitHub no nos d muitas dicas visuais de que n

pode comparar com a vista master

http://pt.discovermeteor.com/pdf

normal

s estamos olhando um commit

mas voc

e ver num relance que a estrutura do arquivo

39/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

diferente

Therepositoryatcommit142.

AcessandoUmCommitLocalmente

s acabamos de ver como procurar o c

se voc

quiser fazer o mesmo localmente

digo inteiro de um commit online no GitHub

Por exemplo

voc

Mas e

pode querer rodar o app

localmente num espec fico commit para ver como ele deveria se comportar neste ponto do

processo

Para fazer isto

s tomaremos nossos primeiros passos

utilitrio de linha de comando

instalado

Ento clone

Microscope com

bem

neste livro ao menos

com o

git . Para iniciantes, tenha certeza de que voc tem Git

em outras palavras

baixe a c

pia localmente

o reposit

rio do

$ git clone git@github.com:DiscoverMeteor/Microscope.git github_microscope

Esse

github_microscope

estar clonando o app

http://pt.discovermeteor.com/pdf

no final

simplesmente o nome do diret

Supondo que voc

j tem um diret

rio

rio local para o qual voc

microscope

pre existente

40/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

apenas escolha qualquer nome diferente

Vamos

no precisa ter o mesmo nome do GitHub repo

cd

para dentro do reposit

linha de comando

rio para que n

).

s possamos comear a utilizar o utilirrio de

git :

$ cd github_microscope

Agora quando n

s clonamos o reposit

significa que n

Felizmente

outros

rio GitHub

s estamos olhando o c

digo do

h um jeito de voltar no tempo e

,
n

s baixamos todo o c

digo do app

o que

ltimo commit

selecionar

um commit espec fico sem afetar os

Vamos tentar isto

$ git checkout chapter3-1


Note: checking out 'chapter3-1'.
Voc est no estado 'detached HEAD'. Voc pode olhar ao redor, fazer mudana
s experimetnais e comet-las, e voc pode descartar qualquer commits que voc
fez neste estado sem afetar nenhum branch ao efetuar outro checkout.
Se voc quer criar um novo branch para preservar os commits que voc cria, v
oc pode faz-lo (agora ou mais tarde) usando -b com o comando checkout de n
ovo. Exemplo:
git checkout -b new_branch_name
HEAD is now at a004b56... Adicionado template bsicos da lista de artigos e
informao esttica.

Git nos informa que n

importa

s estamos no

detached HEAD

o que significa que at

s podemos observar commits passados mas n

Note que o Git tamb

m tem comandos que permitem voc

onde o Git se

s no podemos modific los

pode pensar nisto como um mago inspecionando o passado atrav

Voc

s de uma bola de cristal

mudar commits passados

Isto

seria mais como um viagem do tempo voltando no tempo e possivelmente pisando numa

borboleta

mas isto est al

http://pt.discovermeteor.com/pdf

).

m do escopo desta breve introduo

41/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

A razo de porque voc

foi capaz de simplesmente digitar

todos os commits do Microscope com o marcador de cap tulo certo

voc

precisaria primeiro encontrar a hash do commit

Mais uma vez

o GitHub faz nossas vidas mais fcil

tagged

Se este no fosse o caso

ou identificador

Voc

chapter3-1 que ns pre

nico

pode encontrar a hash do commit no

canto inferior direito da caixa de cabealho azul do commit

como mostrado aqui

Findingacommithash.

Ento vamos tentar isto com a hash ao inv

s da tag

$ git checkout c7af59e425cd4e17c20cf99e51c8cd78f82c9932


Previous HEAD position was a004b56... Added basic posts list template and st
atic data.
HEAD is now at c7af59e... Augmented the postsList route to take a limit

E finalmente

presente

e se n

s quisessemos parar de olhar pela bola mgia de cristal e voltar para o

s dizemos ao Git que n

s queremos check out o master branch

$ git checkout master


http://pt.discovermeteor.com/pdf

42/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Note que voc

processo

update

at

pode tamb

meteor

m rodar o app com o comando

quando em estado

detached HEAD

Voc

pode precisar rodar um rpido

primeiro se o Meteor reclamar de pacotes faltando

em qualquer ponto do

j que o c

mrt

digo de pacote no est

inclu do no Git repo do Microscope

PerspectivaHistrica

Aqui mais outro cenrio comum

que voc

mudou

no tinha visto antes

Voc

voc

est olhando um arquivo e percebe algumas mudanas

A questo

voc

no pode lembrar quando um arquivo

poderia apenas olhar cada commit um a um at

uma forma mais fcil graas ao utens lio Hist

Primeiro

acesse um dos arquivos do reposit

ria do GitHub

rio no GitHub

voc

encontrar o certo

mas h

.
ento encontre o boto

History

GitHubsHistorybutton.

Voc

agora tem uma lista arrumada de todos os commits que afetaram este arquivo em

particular

http://pt.discovermeteor.com/pdf

43/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Displayingafileshistory.

OJogodaCulpa

Para finalizar

vamos dar uma olhada na Culpa

GitHubsBlamebutton.

http://pt.discovermeteor.com/pdf

44/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Esta vista arrumada nos mostra linha por linha quem modificou o arquivo

em outras palavras

e em cada commit

):

quem culpar quando as coisas no esto funcionando mais

GitHubsBlameview.

Agora

Git

uma ferramenta razoavelmente complexa

podemos esperar cobrir tudo num

superf cie do que

pouquinho ser

nico cap tulo

til assim que voc

http://pt.discovermeteor.com/pdf

e o GitHub tamb

Na verdade

poss vel com essas ferramentas

-,

ento n

s no

s mal arranhamos a

Mas felizmente

at

mesmo este

seguir pro resto deste livro

45/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Collections

No primeiro cap tulo

,
n

s falamos sobre a caracter stica central do Meteor

a sincronizao

automtica de informao entre o cliente e o servidor

Neste cap tulo

,
n

s olharemos mais de perto como isso funciona

da pea chave da tecnologia que permite isso

a Meteor Collection

s estamos construindo um aplicativo social de not cias

queremos

desses

ento a primeira coisa que n

fazer uma lista de links que as pessoas postaram

tens de

e observaremos a operao

.
N

s chamaremos cada um

post

Naturalmente

s precisamos armazenar esses posts em algum lugar

com um banco de dados Mongo que roda no servidor e

Ento

Meteor vem integrado

o seu banco de mem

especialmente Mongo

ou o comentrio que eles esto digitando agora

cont

s queremos dizer que

diferente

a mesma para todos usurios

atrav

por exemplo

nica

Por can

Uma coleo

s de publica

es e assinaturas

um tipo de estrutura de

toma conta de sincronizar

Vamos ver como

s queremos que nossos posts sejam permanentes e compartilhados entre usurios

o banco de

s comearemos criando uma coleo chamada

no fez isso crie uma pasta

posts.js

dentro dela

nica

cada usurio pode estar numa pgina

informao em tempo real de e para o navegador de cada usurio conectado e at

dados Mongo

a mesma para todos

armazenada no Meteor na Coleo

dados especial que

o servidor

m a fonte de informao permanente e can

mas a lista mestre de posts

Esta informao

),

ria persistente

apesar do navegador de um usurio poder conter algum tipo de estado

que pgina eles esto

collections/

Ento adicione

Posts

para armazen los

na ra z do seu aplicativo

Se voc

ento

ainda

e ento um arquivo

Posts = new Meteor.Collection('posts');

http://pt.discovermeteor.com/pdf

46/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

collections posts js

Commit41
Added a posts collection

Ver no GitHub

digo dentro de pastas que no so

Posts

Ento a coleo

Lanar Instncia

client/

server/

ou

rodaro em ambos contextos

est dispon vel para tanto cliente quanto servidor

coleo faz em cada ambiente

Entretanto

o que a

bem diferente

UsarVarOuNoUsarVar?

Em Meteor

a palavra chave

var

s queremos fazer a coleo

limita o escopo de um objeto ao arquivo atual

Posts

dispon vel para todo nosso aplicativo

porqu

No servidor

s no estamos usando a palavra chave

de dados padro

real coleo can

Neste sentido

No cliente entretanto

nica

var .

Aqui

este

a coleo tem o trabalho de conversar com o banco de dados Mongo

escrever qualquer mudanas

e ler e

pode ser comparada a uma biblioteca de bancos

a coleo

A coleo do lado do cliente

uma c

pia segura de um subconjunto da

constantemente e

em sua maior parte

transparentemente mantida atualiza com esse subconjunto em tempo real

ConsolevsConsolevsConsole

Neste cap tulo

,
n

s comearemos a fazer uso do browser console

confundido com o terminal ou o Mongo shell

que no deve ser

Aqui est uma rpida demo sobre

cada um deles

Terminal

http://pt.discovermeteor.com/pdf

47/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

TheTerminal

Chamado do seu sistema operacional

Lado do Servidor

console.log()

chama o output aqui

: $.

Prompt

Tamb

m conhecido por

Shell

Bash

ConsoledoNavegador

TheBrowserConsole

Chamando de dentro do navegador

Lado do Cliente

http://pt.discovermeteor.com/pdf

console.log()

executa c

digo JavaScript

chama o output aqui

.
48/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Prompt

Tamb

m conhecido por

JavaScript Console

DevTools Console

MongoShell

TheMongoShell

Chamado pelo terminal atrav

s de

meteor mongo .

D acesso direto ao banco de dados do seu aplicativo

: >.

Prompt

Tamb

m conhecido por

Note que em cada caso

parte do comando

prompt

voc

E voc

Mongo Console

no deve digitar o caracter prompt

( $ , ,

>

ou

como

pode assumir que qualquer linha que no comece com o

o resultado do comando anterior

ColeesdoLadodoServidor

No servidor

servidor

a coleo atua como uma API dentro do seu banco de dados Mongo

isto permite que voc

escreva comandos Mongo como

Posts.update() , e eles faro mudanas na coleo posts

Para ver dentro do banco de dados Mongo

meteor

comando

meteor mongo

http://pt.discovermeteor.com/pdf

Posts.insert()

),

e v at

para inicar um Mongo shell

digo do

ou

armazenada dentro do Mongo

abra uma segunda janela do terminal

ainda est rodando na sua primeira

No c

o diret

rio do aplicativo

no qual voc

enquanto o

Ento

rode o

pode digitar comandos

49/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Mongo

e como costumeiramente

exemplo

voc

vamos inserir um novo post

pode sair com o atalho de teclado

ctrl+c . Por

> db.posts.insert({title: "A new post"});


> db.posts.find();
{ "_id": ObjectId(".."), "title" : "A new post"};

The Mongo Shell

MongonoMeteor.com

*.

Note que quando hospedar um aplicato em

meteor com

acessar a Mongo shell do seu aplicativo hospedado com

E j que estamos falando disso

digitando

voc

tamb

voc

pode tamb

meteor mongo myApp .

m pode acessar os logs do seu aplicativo

meteor logs myApp .

A sintaxe do Mongo

familiar

j que utiliza uma interface JavaScript

nenhuma outra manipulao de informao na Mongo shell

.
N

s no faremos

mas n

s poderemos dar uma

olhada nela de tempos em tempos para nos assegurar do que est l

ColeesdoLadodoCliente

Cole

es se tornam mais interessantes do lado do cliente

Meteor.Collection('posts');

no cliente

o que voc

no navegador da verdadeira coleo Mongo

cliente ser um

informao

cache

est criando

Quando n

declara

Posts = new

um cache em tempo real

s falamos sobre coleo do lado do

s queremos dizer que ela cont

m um subconjunto da sua

e oferece um acesso muito veloz a mesma

importante entender este ponto j que

Em geral

Quando voc

fundamental para o modo como o Meteor funciona

a coleo do lado do cliente consiste em um subconjunto de todos os documentos

armazenados na coleo Mongo

http://pt.discovermeteor.com/pdf

at

mesmo porque n

s geralmente no queremos mandar

50/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

todo nosso banco de dados para o cliente

Segundo

).

esses documentos esto armazenados na mem

que acess los

basicamente instantneo

ria do navegador

Ento no h viagens lentas at

banco de dados para coletar essa informao quando voc

j que a informao j est pr

o que significa

o servidor ou ao

Posts.find()

chama

no cliente

carregada

IntroduzindoMiniMongo

A implementao do Meteor para o Mongo no lado do cliente se chama MiniMongo

No

uma implementao perfeita ainda

e voc

pode encontrar ocasionalmente

caracter sticas Mongo que no funcionam no MiniMongo

De qualquer forma

todas

as caracter stcas que n

s cobrimos neste livro funcionam de modo similar tanto no

Mongo quanto no MiniMongo

ComunicaoClienteServidor

A pea chave para tudo isso

como a coleo do lado do cliente sincroniza sua informao

com a coleo do lado do servidor com o mesmo nome

Ao inv

s de explicar isto em detalhe

Ento

e acessando o console do navegador em cada

abra a Mongo shell na linha de comando

documento que n

).

no nosso caso

vamos apenas ver o que acontece

Comece abrindo duas janelas no navegador

uma

( 'posts'

Neste ponto

s criamos anteriormente em todos os tr

s devemos ver um

s contextos

nico

> db.posts.find();
{title: "A new post", _id: ObjectId("..")};

The Mongo Shell

http://pt.discovermeteor.com/pdf

51/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Posts.findOne();

{title: "A new post", _id: LocalCollection._ObjectID};

First browser console

Vamos criar um novo post

Em uma das janelas do navegador

rode um comando insert

Posts.find().count();

Posts.insert({title:

'xxx'
Posts.find().count();
2

"A second post"});

First browser console

Sem surpresas

o post chegou na coleo local

Agora vamos checar o Mongo

db.posts.find();

{title: "A new post", _id: ObjectId("..")};


{title: "A second post", _id: 'yyy'};

The Mongo Shell

Como voc

pode ver

escrevermos uma

o post fez todo o caminho at

o banco de dados Mongo

nica linha de c

estritamente falando

s escrevemos uma

digo que conectasse o cliente at

nica linha de c

digo

o servidor

: new

sem n

bem

Meteor.Collection('posts') . Mas isto no tudo

V segunda janela do navegador e digite isto no console do navegador

Posts.find().count();

http://pt.discovermeteor.com/pdf

52/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Second browser console

O post est l tamb

Mesmo apesar de n

com o segundo navegador

atualiza

es

tornar mais

s nunca termos atualizado ou sequer interagido

e n

s certamente no escrevemos nenhum c

Tudo aconteceu magicamente

bvio mais tarde

O que acontece

digo para empurrar

e instantaneamente tamb

apesar que isto se

que a nossa coleo do lado do servidor foi informada pela nossa coleo do

cliente quanto ao novo post

e tomou a misso de distribuir este post at

Mongo e de volta para todas as outras cole

Trazer posts no console do navegador no

esta informao nos nossos templates

to

o banco de dados

post

es

conectadas

til assim

.
N

s aprenderemos como escrever

e no processo transformar nosso simples prot

tipo

HTML em um aplicativo funcional em tempo real

MantendoemTempoReal

Olhar para os cont

udos das nossas Cole

s realmente gostar amos de mostrar

tela

es no console do browser

a informao

uma coisa

e as mundanas a esta informao

Fazendo isto n

s tornaremos nosso aplicativo de uma pgina web com cont

esttico

mas o que

em um aplicativo web em tempo real com cont

udo dinmico e mutvel

na

udo

Vamos descobrir como

PovoandooBancodeDados

A primeira coisa que n

s faremos

por alguma informao no banco de dados

como um arquivo demonstrativo que l

Posts

.
N

s o faremos

um conjunto de informao estruturada na coleo

quando o servidor inicia pela primeira vez

Primeiro

vamos ter certeza que no h nada no banco de dados

.
N

s usaremos

meteor

reset , o qual apaga seu banco de dados e reseta seu projeto. Claro, voc ir querer ser bem
cuidadoso com este comando uma vez que voc

http://pt.discovermeteor.com/pdf

comear a trabalhar em projeto do mundo

53/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

real

Finalize o servidor Meteor

pressionando

ctrl-c

e ento

na linha de comando

rode

$ meteor reset

O comando reset completamente limpa o banco de dados Mongo

desenvolvimento

um comando

til em

onde h uma forte possibilidade do nosso banco de dados cair em um

estado inconsistente

Agora que nosso banco de dados est vazio

carregar tr

s podemos adicionar o c

s posts sempre que o servidor iniciar e encontrar a coleo

digo seguinte que ir

Posts

vazia

if (Posts.find().count() === 0) {
Posts.insert({
title: 'Introducing Telescope',
author: 'Sacha Greif',
url: 'http://sachagreif.com/introducing-telescope/'
});
Posts.insert({
title: 'Meteor',
author: 'Tom Coleman',
url: 'http://meteor.com'
});

Posts.insert({
title: 'The Meteor Book',
author: 'Tom Coleman',
url: 'http://themeteorbook.com'
});

server fixtures js

http://pt.discovermeteor.com/pdf

54/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Commit42

Added data to the posts collection

Ver no GitHub

s colocamos este arquivo no diret

navegador de usurio

insert

chamadas

rio

Lanar Instncia

server/ , ento ele nunca ser lido em nenhum

O c

digo rodar imediatamente quando o servidor comear

no banco de dados para adicionar tr

e far

s posts simples na nossa coleo

Posts . Como ns no construmos nenhuma segurana de informao ainda, no h


diferena real entre fazer isso em um arquivo que roda no servidor ou no navegador

Agora rode seu servidor de novo com

de dados

meteor,

e estes tr

s posts sero carregados no banco

ConectandoainformaoaonossoHTMLcomajudantes

Agora

se n

s abrirmos o console do navegador

s veremos tr

s posts carregados no

MiniMongo

Posts.find().fetch();

Browser console

Para ter esses posts em HTML renderizado

Cap tulo

s podemos usar um ajudante de template

No

3
n

s vimos como o Meteor nos permite ligar um contexto de informao aos nossos

templates do Spacebars para construir vistas HTML de estruturas de dados simples

podemos ligar na nossa coleo informao do exato mesmo modo

substituiremos nosso objeto JavaScript esttico

Falando nisso

sinta se livre para deletar o c

posts_list.js

postsData

digo

.
N

s apenas

com uma coleo dinmica

postsData . Aqui est o que

deve se parecer agora

http://pt.discovermeteor.com/pdf

55/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Template.postsList.helpers({
posts: function() {
return Posts.find();
}
});

client views posts posts

list js

Commit43
Wired collection into

postsList

Ver no GitHub

template

Lanar Instncia

Encontre&Traga

, find()

No Meteor

Quando n

retorna um cursor

s queremos logar seu cont

que

uma fonte de informao reativa

udo

fetch()

s podemos ento usar

no

cursor para transform lo num array

Dentro do aplicativo

o Meteor

cursores sem precisar convert

de voc

fetch()

no ver

inteligente o suficiente para saber como iterar sobre

los explicitamente em arrays primeiro

com tanta frequ

no o usarmos no exemplo acima

Agora

ao inv

).

ncia em c

digo de Meteor

Esta

razo

e o porqu

de

s de puxarmos uma lista de posts como um array esttico de uma varivel

retornamos um cursor para o nosso ajudante

nosso navegador

posts . Mas o que isto faz

Se n

s voltarmos ao

s vemos

http://pt.discovermeteor.com/pdf

56/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Usinglivedata

Ento n

nosso

s podemos claramente ver que o nosso ajudante

{{#each}}

iterou sobre todo o

Posts , e os mostrou na tela. A coleo do lado do servidor puxou os posts do Mongo,

passou o pelo fio at

a nossa coleo do lado do cliente

e nosso ajudante do Spacebars

passou os para o template

Agora

s tomaremos um passo adiante

vamos adicionar outro post atrav

s do console

Posts.insert({

title: 'Meteor Docs',


author: 'Tom Coleman',
url: 'http://docs.meteor.com'
});

Browser console

Olhe de volta ao navegador

http://pt.discovermeteor.com/pdf

voc

deve ver isto

57/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Addingpostsviatheconsole

Voc

acabou de ver a reatividade em ao pela primeira vez

Spacebars para iterar sobre o cursor

quanto a mudanas

Quando n

s diss

mos ao

Posts.find() , ele sabia como observar este cursor

e remendar o HTML da forma mais simples para mostrar a informao

correta na tela

InspecionandomudanasnoDOM

Neste caso

a mudana mais simples poss vel foi a de adicionar mais outro

<div

class="post">...</div> . Se voc quer ter certeza que isto realmente o que

aconteceu

abra o inspector do DOM e selecione o

posts existentes

Agora

voc

ter o mesmo

correspondente a um dos

no console JavaScript

inspector

<div>

ver um

<div>

insira mais outro post

<div>

extra

Quando voc

voltar ao

correspondente ao novo post

existente selecionado

Isto

uma forma

mais voc

ainda

til de dizer quando

elementos foram re renderizados e quando eles foram deixados de lado

ConectandoColees:PublicaeseAssinaturas
http://pt.discovermeteor.com/pdf

58/261

1/8/2015

At

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

ento

produo

autopublish

s t nhamos o pacote

Como seu nome indica

compartilhada na

ativado

es em

este pacote simplesmente diz que cada coleo deve ser

ntegra com cada cliente conectado

que no foi feito para aplica

Isto no

o que realmente queremos

ento vamos desativ lo

Abra uma nova janela do terminal

e digite

$ meteor remove autopublish

Isto tem um efeito instantneo

nossos posts desapareceram

Se voc

Isto

ver no seu navegador agora

porque n

voc

ver que todos os

autopublish

s estvamos dependendo do

para assegurar que a nossa coleo de posts do lado do cliente fosse um espelho de todos os

posts no banco de dados

Eventualmente n

que o usurio de fato precisa ver

enquanto

,
n

s precisaremos assegurar que n

lo

s apenas configuraremos o

todos os posts

).

levando em conta coisas como paginao

Posts

Para faz

s estamos transferindo apenas os posts

s criamos uma simples funo

para ser publicado na

publish()

Mas por

ntegra

que retorna um cursor referente a

Meteor.publish('posts', function() {
return Posts.find();
});

server publications js

No cliente

ao

s precisamos assinar a publicao

.
N

s apenas adicionaremos a linha seguinte

main.js :

Meteor.subscribe('posts');

http://pt.discovermeteor.com/pdf

59/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

client main js

Removed

Commit44

autopublish

and set up a basic publication

Ver no GitHub

Se n

s checarmos o navegador novamente

Lanar Instncia

nossos posts voltaram

Ufa

Concluso

Ento o que n

o que n

s alcanamos

s temos agora

Internet

Bem

apesar de n

s no termos uma interface do usurio ainda

um aplicativo web funcional

usando o console do navegador

s poder amos lanar este aplicativo

comear a postar novas est

rias e v

las aparecer

nos navegadores de outros usurios pelo mundo todo

http://pt.discovermeteor.com/pdf

60/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

PublicaeseSubscries

Publica

es e subscri

dif cil ser dif cil voc

es so uns dos mais importantes conceitos no Meteor

mas pode ser

entender enquanto est comeando

Isso levou a uma s

rie de mal entendidos

as aplica

4.5

SIDEBAR

como a crena de que o Meteor

inseguro

ou que

es Meteor no podem lidar com grandes quantidades de dados

Uma grande parcela do motivo das pessoas inicialmente acharem estes conceitos um pouco

confusos

mgica

que o Meteor faz por n

Embora essa mgica seja muito

obscurecer o que est de fato acontecendo por trs das cenas

).

fazer

,
til

ela pode

o que uma mgica tende a

Ento vamos analisar as camadas dessa mgica e entender o que est acontecendo

OsVelhosTempos

Mas primeiro

vamos olhar para os bons velhos tempos em

havia sido lanado

Vamos dizer que voc

um usurio entra no site

aplicao

o cliente

pode ser a pgina

ltimos

20

quando o Meteor ainda no

est fazendo um simples aplicativo Rails

i e seu navegador

manda uma requisio para sua

12

perceber qual dado o usurio precisa de visualizar

dos resultados da busca

tweets de Bob

e por ai vai

Voc

pode nisso como sendo

Uma vez que o dado correto tenha sido selecionado

traduzir este dado em um belo e leg vel HTML

Na metfora da livraria

View Controller

Finalmente

basicamente

).

Esta

).

a parte

os

um

pediu

o segundo trabalho da aplicao

ou JSON no caso de uma API

isso seria embrulhar o livro que voc

coloc lo em uma bela bolsa

Isso

informao do perfil de usurio da Mary

atendente de livraria navegando entre os corredores para encontrar o livro que voc

Quando

que est vivendo no servidor

O primeiro trabalho da aplicao

(.

2011

View

comprou em uma embalagem e

viso vista

do famoso modelo Model

Modelo Viso Controlador

a aplicao pega o c

http://pt.discovermeteor.com/pdf

digo HTML e manda para o navegador

O trabalho da

61/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

aplicao

finalizado

e agora que tudo est fora de suas mos virtuais voc

cerveja enquanto espera pela pr

pode pegar uma

xima requisio

OCaminhodoMeteor

Vamos rever o que faz o Meteor ser to especial em comparao

inovao do Meteor

que enquanto aplica

Como vimos

a principal

es Rails esto vivas apenas no servidor

aplicativo Meteor inclui um componente no lado do cliente que vai rodar no cliente

navegador

).

um

Colocandoumsubgrupodobancodedadosnocliente.

Isso

at

como um balconista que no apenas encontra o livro pra voc

em casa e l

o livro para voc

http://pt.discovermeteor.com/pdf

noite

mas tamb

m te segue

fato que vamos admitir soar um pouco assustador

).
62/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Essa arquitetura permite ao Meteor fazer vrias coisas legais

Meteor chama de database everywhere

Simplesmente

:
es

primeira

a aplicao Meteor vai mandar o real

dado na rede

).

Segundo

voc

ao inv

s de mandar c

digo HTML para o cliente

data on the

vai ser capaz de acessar o dado instantaneamente sem

).

dado puro e o cliente vai lidar com ele

ter que esperar por uma ida e volta do servidor

lat

).

banco de dados em todos os lugares

Meteor vai pegar uma parte do seu banco de dados e copi lo para o cliente

Isso tem duas grandes implica

wire

principalmente com o que o

latency compensation

compensao de

ncia

Publicao

O banco de dados de um aplicativo pode conter dez mil documentos

privados ou sens veis

sendo alguns destes

Ento obviamente no devemos simplesmente espelhar nosso banco

de dados completamente no cliente

por raz

es de segurana e escabilidade

Ento vamos precisar de uma forma de dizer ao Meteor quais subgrupos de dados podem ser

enviados ao cliente

e vamos realizar isso atrav

Vamos voltar ao Microscope

s de uma publicao

Aqui esto todos os posts do no aplicativo situados no banco de

dados

http://pt.discovermeteor.com/pdf

63/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Todosospostscontidosnonossobancodedados.

Embora esse recurso reconhecidamente no exista no Microscope

de nossos posts tenham sido marcados por linguagem abusiva

eles continuem em nosso banco de dados

(.

i e enviados ao cliente

).

vamos imaginar que alguns

Mesmo que queiramos que

eles no devem estar dispon veis para os usurios

Nossa primeira tarefa vai ser dizer ao Meteor qual dado n

s vamos querer enviar ao cliente

Vamos dizer ao Meteor que desejamos publicar apenas os posts sem marca

http://pt.discovermeteor.com/pdf

es

64/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Excluindopostsmarcados.

Aqui temos o c

digo correspondente

que deve estar no servidor

// no servidor
Meteor.publish('posts', function() {
return Posts.find({flagged: false});
});

Isso assegura para que no exista uma forma de um cliente estar apto a acessar post

marcados

Isso

exatamente a forma que voc

assegure se de publicar dados que voc

cliente

http://pt.discovermeteor.com/pdf

torna uma aplicao Meteor segura

apenas

queira que estejam dispon veis para acesso no

65/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

DDP

Fundamentalmente

voc

pode pensar sobre o sistema de publicao subscrio

como um funil que transfere dados de uma coleo no lado do servidor para uma

coleo no lado do cliente

O protocolo que

Protocol

utilizado neste funil

chamado DDP

).

Protocolo de Dados Distribuidos

que significa Distributed Data

Para aprender mais sobre DDP

pode assistir essa palestra da Real Time Conference por Matt DeBergalis

fundadores do Meteor

),

voc

um dos

ou este screencast por Chris Mather que conduz voc

por

este conceito com um pouco mais de detalhe

Subscrio

Mesmo que seja nossa inteno deixar qualquer publicao no marcada dispon vel para os

clientes

s no podemos simplesmente enviar milhares de publica

es de uma vez

.
N

precisamos de uma forma para os clientes especificarem qual subgrupo de dados eles

precisam em um momento em particular

Todo dado que voc

exatamente ai que as subscri

es entram

se subscrever vai ser espelhado no cliente graas ao Minimongo

implementao do MongoDB feita pelo Meteor no lado do cliente

Por exemplo

vamos dizer que estamos atualmente navegando na pgina perfil de Bob Smith

e somente queremos mostrar seus posts

http://pt.discovermeteor.com/pdf

66/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

SubscrevendonospostsdeBobirespelhlosnocliente.

Primeiro

ir amos alterar nossa publicao para receber um parmetro

// no servidor
Meteor.publish('posts', function(author) {
return Posts.find({flagged: false, author: author});
});

E podemos ento definir este parmetro quando nos subscrevermos nesta publicao no

digo do nosso aplicativo no lado do cliente

// no cliente
Meteor.subscribe('posts', 'bob-smith');

Assim

como torna uma aplicao Meteor escalvel no lado do cliente

subscrever para todos os dados dispon veis

atualmente

Dessa forma

voc

voc

Ao inv

s de se

somente escolhe as partes que voc

precisa

vai evitar sobrecarga de mem

ria no browser no importando

o quo grande seja seu banco de dados no lado do servidor

http://pt.discovermeteor.com/pdf

67/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Encontrando(finding)

Agora os posts de Bob devem ser espalhados em m

JavaScript

mem

,
ria

Ruby

mas n

Nessa hora que

).

Python

tiplas categorias

( )

encontrar

find

por exemplo

Talvez ainda queiramos carregar todos os posts de Bob na

s queremos mostrar somente aqueles da categoria

aparece

JavaScript

por agora

Selecionandoumsubgrupodedocumentosnocliente.

Da mesma forma que fizemos no servidor

,
n

s vamos usar a funo

Posts.find()

para

selecionar um subgrupo de nossos dados

// no cliente
Template.posts.helpers({
posts: function(){
return Posts.find(author: 'bob-smith', category: 'JavaScript');
}
});

Agora que n

funcionam

s temos uma boa compreenso de como as publica

vamos mergulhar e rever alguns padr

http://pt.discovermeteor.com/pdf

es e subscri

es comuns de implementao

es

.
68/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

PublicaoAutomtica(autopublishing)

Se voc

criar um projero Meteor do zero

automaticamente o pacote

(.

i e usando

autopublish

ativado

meteor create , ele vai ter

Para comear

vamos falar sobre o que ele

exatamente faz

autopublish deixar extremamente simples o incio da codificao da sua

O objetivo do

aplicao Meteor

para o cliente

e ele faz isso espelhando automaticamente todos os dados do servidor

tomando conta das publica

es e subscri

es para voc

Autopublish

Como isso funciona

Suponha que voc

http://pt.discovermeteor.com/pdf

tenha uma coleo chamada

'posts'

no servidor

.
69/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

autopublish

Ento

vai automaticamente enviar cada post que encontrar na coleo posts no

Mongo para uma coleo chamada

Se voc

estiver usando

dados sero ub quos

existem problema

'posts'

no cliente

assumindo que exista um

).

autopublish , voc no precisa de pensar sobre publicaes. Os

),

presentes em todos os lugares

bvios de ter uma c

e as coisas se tornam simples

Claro

pia completa do banco de dados da sua aplicao

cacheada na mquina de cada usurio

Por esse motivo

autopublish

no pensou sobre as publica

apropriado somente quando voc

est comeando

e ainda

es

PublicandoColeesCompletas

Uma vez que voc

remova o

autopublish , voc vai rapidamente perceber que todos os seus

dados desapareceram do seu cliente

que o autopublish faz

Uma forma simples de t

publicando uma coleo integralmente

los novamente

Por exemplo

duplicando o

Meteor.publish('allPosts', function(){
return Posts.find();
});

http://pt.discovermeteor.com/pdf

70/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Publicandoumacoleocompleta

s ainda estamos publicando cole

sobre quais cole

Comments

mas

es completas

es publicamos ou no

mas ao menos agora temos controle

Neste caso

estamos publicando a coleo

Posts

no

PublicandoColeesParcialmente

O pr

ximo n vel de controle

os posts que pertencem a um certo autor

http://pt.discovermeteor.com/pdf

publicar somente parte de uma coleo

Por exemplo somente

71/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Meteor.publish('somePosts', function(){
return Posts.find({'author':'Tom'});
});

Publicandoumacoleoparcialmente

http://pt.discovermeteor.com/pdf

72/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

NosBastidores

Se voc

leu a documentao do Meteor sobre publicao

sobrecarregado com as instru

es de se usar

atributos de registros no cliente

aplicativos Meteor que voc

A razo

added()

viu e nunca usam esses m

isso

talvez deve estar

para configurar os

e se deve ter se esforado para conciliar isso com os

_publishCursor() . Voc nunca viu seu uso


publicao

voc

ready()

todos

que o Meteor fornece uma importante conveni

retornar um cursor

ncia

o m

todo

Talvez no diretamente

( . . Posts.find({'author':'Tom'}) )
i e

mas se voc

em uma funo de

exatamente o que o Meteor est usando

Quando o Meteor v

_publishCursor()

tamb

voc

somePosts

que a publicao

adivinhou

retornou um cursor

ele chama

publicando este cursor

automaticamente

Aqui o que o

_publishCursor()

faz

Checa o nome da coleo no lado do servidor

Puxa e encontra documentos a partir do cursor e o envia dentro de uma

coleo no lado do cliente com o mesmo nome

).

.added()

Usando

para fazer

isso

Sempre que um documento for adicionado

estas mudanas para a coleo no lado do cliente

cursor e

.added() , .changed()

No exemplo acima

removido ou alterado

.removed()

Ele usa

ele envia

.observe()

no

).

para fazer isso

s somos capazes de assegurar que o usurio tenha somente os

posts que estiver interessado

os escritos por Tom

dispon veis em cache no lado do

cliente

PublicandoPropriedadesParciais

s vimos como publicar somente alguns de nossos posts

cortando mais coisas

Como anteriormente

mas n

s podemos continuar

Vamos ver como publicar somente propriedades espec ficas

vamos usar

find()

para retornar um cursor

mas dessa vez vamos

excluir alguns campos

http://pt.discovermeteor.com/pdf

73/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Meteor.publish('allPosts', function(){
return Posts.find({}, {fields: {
date: false
}});
});

Publicandopropriedadesparciais

Claro

s tamb

m podemos combinar ambas as t

cnicas

Por exemplo

retornar todos os posts de Tom enquanto deixamos de lado suas datas

assim

se n

s quisermos

podemos escrever

http://pt.discovermeteor.com/pdf

74/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Meteor.publish('allPosts', function(){
return Posts.find({'author':'Tom'}, {fields: {
date: false
}});
});

Resumindo

s vimos como publicar todas as nossas propriedades de todos os documentos e de todas as

cole

es

com

autopublish

at

documentos de algumas cole

Isso cobre o bsico do que voc

como publicar algumas propriedades de alguns

es

pode fazer com as publica

es no Meteor

e estas simples

cnicas devem ser suficientes para a vasta maioria dos casos

As vezes

voc

vai precisar ir al

cobrir isso em outro cap tulo

http://pt.discovermeteor.com/pdf

m combinando

linkando ou fundindo publica

es

s vamos

75/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Rotas

Agora que temos uma lista de artigos

),

utilizadores

que eventualmente podero ser criados pelos

precisamos de uma pgina individual para cada artigo onde os nossos

utilizadores podero discutir cada artigo

s gostar amos que essas pginas pudessem ser acess vel atrav

http://myapp.com/posts/xyz

no formato

nico para cada artigo

onde

s de um permalink

xyz um identificador _id

um URL

de MongoDB

Isto significa que vamos precisar de algum tipo de roteamento para ler o que est na barra de

URL do navegador e mostrar o conte

do correto

AdicionandooPacoteIronRouter

Iron Router

um pacote de roteamento que foi criado especificamente para aplica

es

Meteor

Este no s

ajuda com roteamento

tratar de filtros

associar a

ou seja

es a alguns dos caminhos

). (
.)

que caminho tem acesso a que dados

),

especificar caminhos

Nota

como tamb

e ainda gerir subscri

m permite

es

controlar

o Iron Router foi desenvolvido em parte pelo co

autor do Discover Meteor Tom Coleman

Primeiro

vamos instalar o pacote a partir da Atmosphere

$ mrt add iron-router

Consola

Este comando baixa e instala o pacote iron router na nossa aplicao

por vezes pode ser necessrio reiniciar a sua aplicao Meteor

processo

e depois

mrt

http://pt.discovermeteor.com/pdf

para o iniciar novamente

pronto a usar

usando

ctrl+c

Note que

para matar o

antes de o pacote poder ser utilizado

76/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Note que o Iron Router

poder instalar

um pacote de terceiros

( meteor add iron-router

ou seja

necessrio ter o Meteorite para o

).

no vai funcionar

VocabulriodeRoteador
N

s vamos falar de vrias caracter sticas diferentes do roteador neste cap tulo

tiver alguma experi

ncia com uma framework como Rails

familiarizado com a maioria desses conceitos

voc

Caso contrrio

Se

j estar

segue se um pequeno

glossrio

Rotas

Uma rota

o bloco base do roteamento

Bsicamente

um conjunto de

instru

es que dizem aplicao onde ir e o que fazer quando esta encontra

um URL

.
/terms_of_service
/posts/xyz ,
/search?keyword=meteor .

Caminhos
esttico

Um caminho

parmetros de pesquisa

Segmentos
frente

( / ).
:

Ganchos

um URL dentro da sua aplicao

ou dinmico

As diferentes partes de um caminho

Ganchos so a

es que voc

durante o processo de roteamento

Este pode ser

e ainda incluir

delimitadas por barras para a

gostaria de fazer antes

depois ou at

Um exemplo t pico seria verificar se o

utilizador tem os direitos necessrios antes de mostrar uma pgina

Filtros

Os filtros so simplesmente ganchos que pode definir globalmente

para uma ou mais rotas

Templates de Rota

especifique um

por omisso

mesmo nome da rota

Layout
cont

Cada rota precisa de apontar para um template

o roteador vai procurar por um template com o

Pode pensar num layout como uma moldura digital de fotos

m todo o c

digo HTML que envolve o template atual

mesmo quando o template muda

Controlador

Caso no

Por vezes

voc

Eles

e vai permanecer o

vai perceber que muitos dos seus templates esto

a utilizar os mesmos parmetros

Em vez de duplicar o seu c

fazer com que todas essas rotas herdem de um

roteamento que ir conter toda a l

digo

poss vel

nico controlador de

gica de roteamento

Para mais informao sobre o Iron Router

consulte a documentao completa no

GitHub

http://pt.discovermeteor.com/pdf

77/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Roteamento:MapearURLsparaTemplates

At

agora

,
n

s constru mos o nosso layout utilizando inclus

es de templates hard coded

tais

{{>postsList}} . Por isso, apesar de o contedo da nossa aplicao poder mudar, a

como

estrutura base da pgina

sempre a mesma

um cabealho

com uma lista de artigos por

baixo deste

O Iron Router permite nos outra abordagem ao ficar responsvel pelo que

dentro da tag HTML

s pr

prios

renderizado

<body> . Ou seja, ns no precisamos de definir o contedo dessa tag por

como far amos numa pgina HTML normal

Em vez disso

vamos apontar o

roteador para um template layout especial que contem um ajudante de template

O ajudante

{{yield}}

vai definir uma zona dinmica especial que vai automaticamente

renderizar o template correspondente rota atual

de agora

{{yield}} .

este template especial como o

como conveno

template da rota

):

vamos designar

a partir

Layoutsetemplates.
http://pt.discovermeteor.com/pdf

78/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Vamos comear por criar o nosso layout e adicionar o ajudante

<body>

remover a nossa tag HTML

pr

prio template

O nosso

do

{{yield}} . Primeiro, vamos

main.html , e mover o seu contedo para o seu

, layout.html .
, main.html

agora mais magro

deve ser agora algo como

<head>
<title>Microscope</title>
</head>

client main html

Enquanto que o rec

m criado

layout.html

vai agora conter o layout mais exterior da

aplicao

<template name="layout">
<div class="container">
<header class="navbar">
<div class="navbar-inner">
<a class="brand" href="/">Microscope</a>
</div>
</header>
<div id="main" class="row-fluid">
{{yield}}
</div>
</div>
</template>

client views application layout html

Note que substitu mos a incluso do template

postsList

com uma chamada ao ajudante

yield . Repare que depois desta alterao, no vemos nada no ecr. Isto porque ainda no
dissemos ao roteador o que fazer com o URL

Para comear

o template

desta criar

/ , e neste caso mostrado um template vazio.

,
n

s podemos recuperar o comportamento antigo mapeando o URL raiz

postsList . Vamos criar uma diretoria /lib

na raiz do nosso projecto

para

e dentro

router.js :

http://pt.discovermeteor.com/pdf

79/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Router.configure({
layoutTemplate: 'layout'
});
Router.map(function() {
this.route('postsList', {path: '/'});
});

lib router js

Fizemos duas coisas importantes

Primeiro

dissemos ao roteador para usar o layout que

acabmos de criar como o layout por omisso para todas as rotas

postsList

nova rota chamada

e mapemo la para o caminho

Segundo

definimos uma

/.

Adiretoria /lib
Qualquer coisa que seja colocada dentro da diretoria

/lib garantidamente

carregado antes que qualquer outra coisa na sua aplicao

).

de pacotes inteligentes

Isto faz com que seja um

com a poss vel excepo

ptimo lugar para c

digo de

ajudantes que precisa de estar sempre dispon vel

:
/server ,

Um aviso

note que como a diretoria

/lib

isto significa que os seus conte

/client

no est nem dentro de

nem de

dos estaro dispon veis em ambos os

ambientes

RotascomNome

Vamos esclarecer alguma da ambiguidade

temos um template chamado

Por omisso

realidade

Chammos nossa rota

URL

postsList . O que que se est aqui a passar

ele vai at

procurar por um caminho baseado no nome da rota

ssemos definido um caminho personalizado

path

postsList , mas tambm

o Iron Roter vai procurar por um template com o mesmo nome da rota

tiv

),

na nossa definio de roteador

postsList .

http://pt.discovermeteor.com/pdf

ou seja

Na

se no

que fizemos ao providenciar uma opo

o nosso template no estaria acess vel por omisso no

80/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Outra d

vida poss vel

porque

que precisamos sequer de dar um note s nossas rotas

Dar

nomes a rotas permite nos utilizar algumas caracter sticas do Iron Router que tornam mais

fcil criar links dentro da nossa aplicao

O mais


til

o ajudante Handlebars

{{pathFor}} ,

que devolve o caminho URL de qualquer rota

Queremos que o nosso link principal de casa aponte para a lista de artigos

especificar um URL esttico

por isso em vez de

/ , nos podemos tambm utilizar o ajudante Handlebars. O

resultado final ser o mesmo

mas esta abordagem d nos mais flexibilidade dado que o

ajudante ir sempre fazer output do URL correto mesmo que o caminho no roteador seja

alterado

<header class="navbar">
<div class="navbar-inner">
<a class="brand" href="{{pathFor 'postsList'}}">Microscope</a>
</div>
</header>
//...

client views application layout html

Commit51

Roteamento muito bsico

Ver no GitHub

Lanar Instncia

EsperandoporDados

Caso publique a verso atual da aplicao

ou lance uma instncia utilizando o link acima

notar que a lista aparece vazia por uns momentos antes dos artigos aparecerem

quando a pgina primeiro carrega

dos

posts

Isto

),

ir

porque

no existem artigos para mostrar enquanto a subscrio

no carrega os dados dos artigos do servidor

Seria muito melhor para a experi

http://pt.discovermeteor.com/pdf

ncia de utilizao se pud

ssemos disponibilizar algum

81/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

feedback visual que algo est a acontecer

Por sorte

e que o utilizar deve esperar alguns momentos

o Iron Router tem uma forma fcil de fazer isso

vamos

waitOn

esperar pela

subscrio

Router.configure({
layoutTemplate: 'layout',
loadingTemplate: 'loading',
waitOn: function() { return Meteor.subscribe('posts'); }
});
Router.map(function() {
this.route('postsList', {path: '/'});
});

lib router js

Vamos por partes

Primeiro

modificmos o bloco

o nome do template de carregando

enquanto esperamos por dados

Segunda

tamb

que vamos criar a seguir

m adicionamos uma funo

O que isto significa

Router.configure()

para dar ao roteador

para onde se deve redirecionar

waitOn , que devolve a nossa subscrio posts .

que o roteador vai garantir que a subscrio

de mandar o utilizador pela rota que ele pediu

posts

est carregada antes

Note que como estamos a definir a nossa funo de

waitOn

globalmente ao n vel da rota

esta sequ

ncia apenas vai acontecer uma vez quando o utilizador acede sua aplicao pela

primeira vez

Depois disso

os dados vo estar na mem

precisar de esperar por eles novamente

E como n

ria do navegador e a rota no vai

s estamos a deixar o roteador gerir a nossa subscrio

com segurana do

Normalmente

utilizao

main.js

que deve agora estar vazio

).

uma boa ideia esperar pelas suas subscri

mas tamb

voc

pode agora remov

no apenas pela experi

la

ncia de

m porque isto significa que se pode assumir com segurana que os

dados vo estar dispon veis nos templates

http://pt.discovermeteor.com/pdf

es

Isto elimina a necessidade de lidar com templates

82/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

serem renderizados antes de os dados subjacentes estarem dispon veis

coisa que

normalmente requer abordagens no ideais

A pea final do puzzle

o template de carregamento

um template de carregamento animado engraado

mrt add spin , e depois crie o template loading

Vamos usar o pacote

spin

para criar

Este pode ser adicionado com o comando

da seguinte forma

<template name="loading">
{{>spinner}}
</template>

client views includes loading html

{{>spinner}} um template parcial contido no pacote spin . Apesar de este

Note que

template parcial vir de


fora

da nossa aplicao

,
n

s podemos utiliz lo como qualquer outro

template

Commit52

Esperar na subscrio do artigo

Ver no GitHub

http://pt.discovermeteor.com/pdf

Lanar Instncia

83/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

UmPrimeiroOlharSobreAReatividade
Reatividade

um conceito chave de Meteor

abordado o t

pico

e apesar de ainda no termos realmente

o nosso template de carregamento d nos um primeiro olhar

sobre este conceito

Redirecionar para um template de carregamento se os dados ainda no foram

carregados est muito bem

mas como

que o roteador sabe quando deve

redirecionar o utilizador de volta para a pgina correta assim que os dados foram

carregados

Por agora

por aqui

vamos apenas dizer que isto

Mas no se preocupe

exatamente onde a reatividade entra

e ficar

vai aprender mais sobre o assunto brevemente

RoteandoParaUmPostEspecfico

Agora que vimos como rotear para o template

os detalhes de um

nico artigo

Existe apenas um problema

pode haver centenas deles

postsList , vamos criar uma rota para mostrar

:
n

s no podemos prosseguir e definir uma rota por artigo

Neste caso

necessrio definir uma

essa rota mostrar qualquer artigo que queiramos

Para comear

nica rota dinmica

j que

e fazer

vamos criar um novo template que simplesmente renderiza o mesmo template

de artigo que utilizmos anteriormente na lista de artigos

<template name="postPage">
{{> postItem}}
</template>

/ _

client views posts post

page html

Posteriormente vamos adicionar mais elementos a este template

),

comentrios

como por exemplo

mas por agora este vai servir simplesmente como um contentor para a nossa

http://pt.discovermeteor.com/pdf

84/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

{{> postItem}} .

incluso

Vamos criar outra rota com nome

para o template

desta vez mapeando caminhos URL na forma

/posts/<ID>

postPage :

Router.map(function() {
this.route('postsList', {path: '/'});
this.route('postPage', {
path: '/posts/:_id'
});
});

lib router js

A sintaxe especial

rota na forma

:_id

indica ao roteador duas coisas

/posts/xyz/ , onde

que for que encontrar neste


xyz


xyz

primeiro

pode ser qualquer coisa

dentro de uma propriedade

para combinar qualquer

Segundo

_id

na lista

para por seja o

params

do

roteador

Note que estamos apenas a usar

forma de saber se voc

_id

por uma questo de conveniencia

O roteador no tem

_id , ou uma string aleatria de

lhe est a passar realmente um

caracteres

Estamos agora a rotear para o template correto

sabe o

como

_id

do artigo que queremos mostrar

mas ainda nos falta alguma coisa

mas o template no faz ideia de qual

o roteador

Ento

que damos a volta a este problema

Felizmente

o roteador tem uma soluo inteligente

dados do template

este deixa especificar o contexto de

Pode se pensar no contexto de dados como o recheio dentro de um bolo

delicioso feito de templates e layouts

De forma simples

o que se usa para encher o

template

http://pt.discovermeteor.com/pdf

85/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Ocontextodedados.

No nosso caso

_id

usando o

podemos ir buscar o contexto de dados adequado procurando pelo artigo

que obtivemos do URL

Router.map(function() {
this.route('postsList', {path: '/'});
this.route('postPage', {
path: '/posts/:_id',
data: function() { return Posts.findOne(this.params._id); }
});
});

lib router js

Assim

cada vez que o utilizador acede a esta rota

vai pass lo ao template

uma pesquisa

Lembre se que

findOne

e que providenciar apenas um

http://pt.discovermeteor.com/pdf

_id

ele vai encontrar o artigo correspondente e

devolve um

nico artigo que corresponde a

como argumento

um atalho para

{_id:
86/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

id} .

Dentro da funo

e podemos utilizar

data

dados em portugu

this.params

indicmos prefixando as com

, this

para uma rota

para aceder s partes com nome da rota

dentro da nossa

corresponde rota atual

path .

partes que

MaisSobreContextodeDados

Ao definir o contexto de dados de um template

pode controlar o valor de

this

dentro de um ajudante de template

Isto

{{#each}} , que

normalmente feito implicitamente com o iterador

automaticamente define o contexo de dados de cada iterao para o item atual da

interao

{{#each widgets}}
{{> widgetItem}}
{{/each}}

Mas tamb

{{#with}} , que

m o podemos fazer explicitamente utilizando

simplesmente diz

podemos escrever

toma este objecto

e aplica lhe este template

Por exemplo

{{#with myWidget}}
{{> widgetPage}}
{{/with}}

Tamb

poss vel obter o mesmo efeito passando o contexto como um argumento

da chamada ao template

Ou seja

o bloco anterior de c

digo pode ser reescrito

como

{{> widgetPage myWidget}}

http://pt.discovermeteor.com/pdf

87/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

UtilizandoUmAjudantedeRoteadorComNomeDinmico

Por fim

temos de ter a certeza que estamos a apontar para o lugar certo quando queremos

fazer um link para um artigo individual

Novamente

podemos usar algo como

<a

href="/posts/{{_id}}"> , mas usar um ajudante de roteador mais seguro.


postPage , por isso podemos usar um ajudante {{pathFor

Chammos a rota do artigo

'postPage'}} :

<template name="postItem">
<div class="post">
<div class="post-content">
<h3><a href="{{url}}">{{title}}</a><span>{{domain}}</span></h3>
</div>
<a href="{{pathFor 'postPage'}}" class="discuss btn">Discuss</a>
</div>
</template>

/ _

client views posts post

item html

Commit53
Rotear para uma

Ver no GitHub

Mas espera

como exatamente

/posts/xyz

Na realidade

Assim

_id

xyz

em

_id .

suficientemente inteligente para perceber isso por si pr

de alguma esp

cie

o roteador vai procurar por este

dados do ajudante

Lanar Instncia

no lhe estamos a passar nenhum

estamos a dizer ao roteador para usar a rota

precisa de um

nica pgina de artigo

que o roteador sabe onde ir buscar a parte do

No final de contas

o Iron Router

prio

postPage , e o roteador sabe que esta rota

dado que foi assim que definimos a nossa

_id

no local mais l

gico dispon vel

.
N

path .

o contexto de

{{pathFor 'postPage'}} , ou notras palavras this . E acontece que o

http://pt.discovermeteor.com/pdf

88/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

this

nosso

corresponde a um artigo

Alternativamente

tamb

procurar pela propriedade

que

!)

surpresa

tem uma propriedade

poss vel dizer explicitamente ao roteador onde

_id .

que ele deve

_id , passando um segundo argumento ao ajudante

ou seja

{{pathFor 'postPage' someOtherPost}} . Um possvel cenrio onde este padro poder ser
usado

ao construir o link para o artigo anterior ou seguinte numa lista

Para verificar se funciona corretamente

navegue para a lista de artigos e clique num dos links

Discuss . Deve ver algo como:

Umanicapginadeartigo.

http://pt.discovermeteor.com/pdf

89/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

HTML5pushState
Uma coisa a perceber

HTML

que estas mudanas de URL esto a ser feitas utilizando

pushState

O Roteador apanha cliques em URLs que so internos ao site

navegue para fora da aplicao

estado da aplicao

es necessrias ao

Se tudo funcionar corretamente

facto

e em vez disso faz as altera

e evita que o navegador

a pgina deve mudar de forma instantnea

De

s vezes as coisas mudam to rpido que pode ser necessria uma transio de

pgina

Isto est fora do ambito deste cap tulo

interessante

mas no deixa de ser um t

pico

http://pt.discovermeteor.com/pdf

90/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

ASesso

Meteor

5.5

SIDEBAR

um framework reativo

O que significa

que quando os dados so alterados

coisas

em sua aplicao mudam sem voc

ter que explicitamente fazer alguma coisa

s j vimos isso em ao e como nossos templates mudam quando os dados e as rotas

mudam

Vamos mergulhar fundo e saber como isso funciona nos pr

ximos cap tulos

mas por agora

gostar amos de introduzir algumas propriedades bsicas da reatividade que so

extremamente

teis para maioria das aplica

es

AMeteorSession

Agora no Microscope

o estado atual da aplicao do usurio est completamente contido na

URL que ele est procurando

Mas em vrios casos

voc

).

e o banco de dados

verso atual do usurio da aplicao

).

escondido

A Session

global

A Session

vai precisar armazenar algum estado ef

por exemplo

h uma sesso

como coisas ruins

e ela

Ele

acess vel em todo lugar

mas neste caso a sesso

relevante a

se um elemento est exposto ou

uma forma conveniente de se fazer isso

um dado reativo global armazenado

mero que s

global no sentido de um objeto singleton

Variveis globais geralmente so vistas

usada como um ve culo central de comunicao

para diferentes partes da aplicao

Mudandoa

Esta

sesso

Session

est dispon vel como

Session . Para configurar um valor de sesso, voc pode

chamar

Session.set('pageTitle',

http://pt.discovermeteor.com/pdf

'A different title');


91/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Browser console

Voc

pode ler o dado de volta com

reativa de dados

Session.get('mySessionProperty'); . Isso uma fonte

que significa que se voc

coloc la em um helper

voc

ver a sa da do helper

mudando reativamente quando a varivel Session for alterada

Para testar isso

adiocione o seguinte c

digo no modelo do layout

<header class="navbar">
<div class="navbar-inner">
<a class="brand" href="{{pathFor 'postsList'}}">{{pageTitle}}</a>
</div>
</header>

client views application layout html

Template.layout.helpers({
pageTitle: function() { return Session.get('pageTitle'); }
});

client views application layout js

A atualizao automatica do Meteor

varveis Session

Session.set()

m disso se n

hot code reload

A different title

HCR

conserva as

na barra de navegao

Se no

novamente

s mudarmos o valor mais uma vez

conhecida como

ento podemos agora ver

apenas digite o comando

Al

),

novamente no console do browser

vamos ver outro t tulo sendo mostrado

Session.set('pageTitle',

'A brand new title');

Browser console

http://pt.discovermeteor.com/pdf

92/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Session est dispon vel globalmente

lugar da aplicao

ento estas mudanas podem ser feitas em qualquer

Isso nos d muio poder

mas pode tamb

m ser uma armadilha se usado

exageradamente

MudanasIdnticas

Se voc

Session.set()

modificar uma varivel Session com

um valor id

ntico

o Meteor

evitar a chamada do m

mas configur la com

inteligente o suficiente para desviar a cadeia reativa

todo

IntroduzindooAutorun

Vimos um exmplo de fonte de dados reativa

template helper

).

modelo auxiliar

template helpers

e tamb

m vimos isso em ao dentro de um

Mas enquanto alguns contextos no Meteor

so inerentemente reativos

a maioria do nosso c

como os

digo Meteor continua

sendo o bom e velho JavaScript no reativo

Vamos supor que temos o seguinte trecho de c

digo em algum lugar de nosso aplicativo

helloWorld = function() {
alert(Session.get('message'));
}

Mesmo que estejamos chamando uma varivel Session

no

reativo

significando que n

o contexto em que a chamada

s no vamos ter um novo

alert

feita

toda as vezes que

mudarmos a varivel

Ai

onde o Autorun entra

Como o nome implica

o c

digo dentro de um bloco

autorun

vai

rodar automaticamente e continuar rodando toda vez que a fonte de dados reativa usada

mudar

Tente digitar isso dentro do console do navegador

http://pt.discovermeteor.com/pdf

93/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Deps.autorun(

function() { console.log('Value is: ' + Session.get('pageTit

le')); } );
Value is: A brand new title

Console do navegador

Como se poderia esperar

o bloco de c

retornando esse dado para o console

Session.set('pageTitle',

Value is: Yet another value

digo fornecido dentro de

Agora

autorun

vamos tentar mudar o t tulo

roda uma vez

'Yet another value');

Console do navegador

Mgica

Como o valor da sesso mudou

todo novamente

sabia que tinha que rodar este conte

re imprimindo o novo valor no console

Agora voltando ao exemplo anterior

do

se n

que nossa varivel Session for alterada

um bloco

autorun

s queremos disparar um novo alerta toda as vezes

tudo que temos que fazer

envolver nosso c

digo em

autorun :

Deps.autorun(function() {
alert(Session.get('message'));
});

Como acabamos de ver

autoruns pode ser muito

til para rastrear fontes de dados e reagir

imperativamente com elas

HotCodeReload

Durante nosso desenvolvimento do Microscope

propriedades do Meteor que salvam tempo

de nossos arquivos de c

http://pt.discovermeteor.com/pdf

digos

temos tirado proveito de uma das

Hot Code Reload

( ).
HCR

Sempre que salvamos um

o Meteor detecta a mudana e reinicia o servidor

informando

94/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

a cada cliente do recarregamento da pgina

Isso

.
,

similar a uma atualizao automtica da pgina

Para saber qual

essa diferena

mas com uma importante diferena

comece reconfigurando a varivel Session que temos usado

Session.set('pageTitle', 'A
Session.get('pageTitle');

brand new title');

'A brand new title'

Browser console

Se n

naturalmente vai ser perdida

s recarregarmos nossa janela do navegador manualmente

uma vez que seria criada uma nova sesso

s dispararmos um hor code reload

a pgina vai ser recarregada

nossa varivel Session

por exemplo

).

Do outro lado

se

salvando um de nossos arquivos de c

mas a varivel session vai continuar configurada

digo

Tente agora

Session.get('pageTitle');

'A brand new title'

Browser console

Ento se estivermos usando variveis de sesso para rastrear exatamente o que o usurio est

fazendo

o HCR deve ser transparente para o usurio

as variveis de sesso

pois isso vai preservar o valor de todas

Isso nos permite fazer o deploy de novas vers

es em produo de

nossas aplica

es Meteor com a confiana de que nossos usurios vo ser minimamente

interrompidos

Considere isso por um instante

Se n

s podemos manter todo o nosso estado na URL e na

sesso

s podemos transparentemente mudar o c

digo fonte rodando por baixo de cada

aplicao do cliente com uma interrupo m nima

Vamos checar o que acontece quando n

http://pt.discovermeteor.com/pdf

s atualizamos a pgina manualmente

95/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Session.get('pageTitle');

null

Browser console

Quando n

s recarregamos a pgina

s perdemos a sesso

Com o HCR

o Meteor salva a

sesso em local storage no seu navegador e a carrega novamente depois do recarregamento

Entretanto

o comportamente alternativo no recarregamento expl cito faz sentido

usurio recarrega a pgina

se um

como se ele tivesse ido para a mesma URL novamente

e ele

deseja resetar ao ponto inicial que qualquer usurio vai ver quando visita a URL

As importantes li

1.

es em tudo que foi visto so

Sempre armazene esados de usurio na Session ou na URL

assim os usurios sero

minimamente interrompidos quando um HCR acontecer

2.

Armazene qualquer estado que voc

dentro da pr

queira que seja compartilhvel entre usurios

pria URL

http://pt.discovermeteor.com/pdf

96/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

AdicionandoUsurios

At

ento

s conseguimos criar e mostrar algumas informa

de forma sensata e conectar tudo num simples prot

s at

vimos que a nossa UI

es demonstrativas e estticas

tipo

responsiva a mudanas nas informa

ou modificada aparece imediatamente

no podemos enviar informao

Vamos ver como n

Por

es

nosso site est paralisado pelo fato de que n

Na real

e informao inserida

s ainda nem temos usurios

s podemos consertar isso

Contas:usuriosdeformasimples

Na maioria dos web frameworks

voc

ainda

,
,

Por sorte

Meteor te d cobertura

uma questo familiar

to fcil quanto poderia ser

Claro

Pior

es de

Graas ao modo como os pacotes do Meteor podem

digo tanto no servidor

tem que lidar com OAuth e outros esquemas de autentica

JavaScript

quanto no cliente

JavaScript

HTML

s podemos ter um sistema de contas quase por nada

mas no

as coisas tendem a ficar feias rpido

contribuir com c

),

lo quase em cada projeto

assim que voc

terceiros

CSS

tem quer faz

adicionar contas de usurio

s poder amos apenas usar a UI nativa do Meteor para contas

mas j que n

accounts-ui-bootstrap-dropdown

).

estilizao

s constru mos todo nosso app com Bootstrap

no lugar

Na linha de comando

com

mrt add accounts-ui

s iremos usar o pacote

no se preocupe

,
a

nica diferena

na

s digitamos

$ mrt add accounts-ui-bootstrap-dropdown


$ mrt add accounts-password

Terminal

Esses dois comandos fazem os templates especiais de conta dispon veis para n

http://pt.discovermeteor.com/pdf

97/261

1/8/2015

podemos inclu

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

{{loginButtons}} . Uma dica til: voc

los no nosso site usando o ajudante

exemplo

: {{loginButtons align="right"}} .

align

pode controlar em que lado o seu log in dropdown aparece usando o atributo

s adicionaremos esses bot

comeando a ficar grande

inclu remos em

es ao nosso cabealho

).

header

E j que esse cabealho est

vamos dar mais espao a ele com um template pr

por

prio

(
n

s o

client/views/includes . Ns tambm usaremos alguma marcao extra e

classes do Bootstrap para garantir que tudo parea

timo

<template name="layout">
<div class="container">
{{>header}}
<div id="main" class="row-fluid">
{{yield}}
</div>
</div>
</template>

client views application layout html

<template name="header">
<header class="navbar">
<div class="navbar-inner">
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-col
lapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<a class="brand" href="{{pathFor 'postsList'}}">Microscope</a>
<div class="nav-collapse collapse">
<ul class="nav pull-right">
<li>{{loginButtons}}</li>
</ul>
</div>
</div>
</header>
</template>

client views includes header html

http://pt.discovermeteor.com/pdf

98/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Agora

quando n

s navegamos para o nosso aplicativo

s vemos os bot

es de login das

contas no canto direito do nosso site

MeteorsbuiltinaccountsUI

s podemos us los para cadastrar

logar

requerir mudana de senha

site simples precisa para contas baseadas em senha

e todo resto que um

Para informar ao nosso sistema de contas que n

um username

s queremos que os usurios faam log in via

,
n

s simplesmente adicionamos um bloco de configurao

config.js

novo arquivo

dentro de

Accounts.ui

num

client/helpers :

Accounts.ui.config({
passwordSignupFields: 'USERNAME_ONLY'
});

client helpers config js

http://pt.discovermeteor.com/pdf

99/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Commit61
Added accounts and added template to the header

Ver no GitHub

Lanar Instncia

CriandoNossoPrimeiroUsurio

V em frente e cadastre se com uma conta

username

o boto

Sign in

mudar para mostrar o seu

Isto confirma que uma conta de usurio foi criada para voc

Mas de onde a

informao de conta de usrio est vindo

Ao adicionar o pacote

acessada com

contas , o Meteor criou uma nova coleo especial, a qual pode ser

Meteor.users . Para v

la

abra o console do seu navegador e digite

Meteor.users.findOne();

Browser console

O console dever retornar um objeto representando o seu objeto usurio

olhada

voc

pode ver que seu username est l

identifica voc

Note que voc

tamb

assim como uma

_id

se voc

der uma

que unicamente

m pode chamar o atual usurio logado com

Meteor.user() .

Agora log out e cadastre se com um novo username

segundo usurio

Mas espere

vamos rodar

. Meteor.user()

deve retornar agora um

Meteor.users.find().count();

Browser console

http://pt.discovermeteor.com/pdf

100/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

O console retorna

1.

Espere

no deveria ser

logar com o primeiro usurio de novo

voc

O primeiro usurio foi deletado

ver que este no

o caso

Vamos ter certeza e checar o armazenamento de informao can

Mongo

s logaremos no Mongo

( meteor mongo

nico

no seu terminal

Se voc

tentar

o banco de dados

e checaremos

> db.users.count()
2

Mongo console

H definitivamente dois usurios

navegador

Ento por que n

s conseguimos ver apenas um por vez no

UmMistriodaPublicao!

Se voc

pensar de novo no Cap tulo

4,

talvez voc

se lembre que ao desativiar o

autopublish , ns paramos as colees de automaticamente enviar toda informao do

servidor para cada verso local da coleo dos clientes

s precisamos criar um par de

publicao e assinatura para conectar a informao

Ainda no configuramos nenhum tipo de publicao de usurio

Ento como podemos ver

informao de qualquer usurio que seja

A resposta

que o pacote accounts de fato

atual usurio logado sem se importar com o resto

auto publica

as informaos bsicas de conta do

Se no o fizesse

ento esse usurio nunca

conseguiria logar no site

O pacote accounts apenas publica o usurio atual alis

pode ver os detalhes da conta de outro

Isto explica porque um usurio no

Ento a publicao est apenas publicando um objeto usurio por usurio logado

quando voc

no est logado

http://pt.discovermeteor.com/pdf

).

e nenhum

101/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Ainda mais

documentos na nossa coleo usurios no parecem conter os mesmos campos

no servidor e no cliente

Em Mongo

um usurio tem um monte de informao nele

Para v

la

apenas v de volta ao terminal Mongo e digite

> db.users.findOne()
{
"createdAt" : 1365649830922,
"_id" : "kYdBd9hr3fWPGPcii",
"services" : {
"password" : {
"srp" : {
"identity" : "qyFCnw4MmRbmGyBdN",
"salt" : "YcBjRa7ArXn5tdCdE",
"verifier" : "df2c001edadf4e475e703fa8cd093abd4b63afccbca48f
ad1d2a0986ff2bcfba920d3f122d358c4af0c287f8eaf9690a2c7e376d701ab2fe1acd53a5bc
3e843905d5dcaf2f1c47c25bf5dd87764d1f58c8c01e4539872a9765d2b27c700dcdedadf5ac
82521467356d3f91dbeaf9848158987c6d359c5423e6b9cabf34fa0b45"
}
},
"resume" : {
"loginTokens" : [
{
"token" : "BMHipQqjfLoPz7gru",
"when" : 1365649830922
}
]
}
},
"username" : "tmeasday"
}

Mongo console

Por outro lado

no navegador o objeto usurio

digitar o comando equivalente

muito reduzido

como voc

pode ver ao

Meteor.users.findOne();

Object {_id: "kYdBd9hr3fWPGPcii", username: "tmeasday"}

Browser console

http://pt.discovermeteor.com/pdf

102/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Este examplo nos mostra como uma coleo local pode ser um subconjunto seguro do

verdadeiro banco de dados

para funcionar

neste caso

O usurio logado v

).

logar

Este

apenas o suficiente do conjunto de dados

um padro

til a se aprender

como voc

ver mais

adiante

Isso no significa que voc

quiser

Voc

na coleo

no possa tornar p

blica mais informao sobre o usurio se voc

pode checar o Meteor docs para ver como opcionalmente publicar mais campos

Meteor.users .

http://pt.discovermeteor.com/pdf

103/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Reatividade

Se as cole

es so as ferramentas centrais do Meteor

a crosta que faz o

til

es transformam radicalmente a forma como seu aplicativo lida com mudanas na

informao

Ao inv

s de ter de checar por mudanas na informao manualmente

atrav

ento reatividade

centro

Cole

6.5

SIDEBAR

s de chamadas AJAX

e ento costurar essas mudanas no HTML

vulgo

mudanas na

informao podem ento vir a qualquer momento e serem aplicadas interface do usurio

sem problemas

Tome um momento para pensar nisso direito

por trs das cortinas

o Meteor

mudar qualquer parte da interface do usurio quando uma coleo subjacente

A forma imperativa para se fazer isso seria usar

O c

atualizada

.observe() , uma funo cursor que dispara

callbacks quando documentos correspondentes ao cursor mudam

fazer mudanas ao DOM

capaz de

o HTML renderizado da nossa pgina web

digo resultante se pareceria com algo assim

s ento poder amos

atrav

s desses callbacks

Posts.find().observe({
added: function(post) {
// when 'added' callback fires, add HTML element
$('ul').append('<li id="' + post._id + '">' + post.title + '</li>');
},
changed: function(post) {
// when 'changed' callback fires, modify HTML element's text
$('ul li#' + post._id).text(post.title);
},
removed: function(post) {
// when 'removed' callback fires, remove HTML element
$('ul li#' + post._id).remove();
}
});

Voc

j pode provavelmente perceber como tal c

Imagine lidar com mudanas em cada atributo da postagem

http://pt.discovermeteor.com/pdf

digo ficar complexo bem rapidamente

e ter de fazer mudanas

104/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

<li>

complexas ao HTML dentro dos

da postagem

fronteirios que podem surgir quando n

Sem mencionar em todos os casos

s comeamos a precisar de m

informao que todas podem mudar em tempo real

ltiplas fontes de

Usar observe() ?

Quando

devemos

Usar o padro acima

widgets de terceiros

s vezes necessrio

Por exemplo

especialmente quando se lida com

vamos imaginar que n

s queremos adicionar e

remover alfinetes de um mapa em tempo real baseado em informao de uma

Coleo

digamos

Em tais casos

conversar

exemplo

voc

es dos usurios logados agora

observe()

precisar fazer callbacks do

para fazer o mapa

com a coleo do Meteor e como reagir s mudanas da informao

voc

dropPin()

).

para mostrar as localiza

precisaria dos callbacks

removePin()

ou

added

removed

para chamar os m

Por

todos

da API do mapa

Umapproachdeclarativo

O Meteor prov

declarativo

a n

s uma forma melhor

cada poss vel mudana

reatividade

a qual

em sumo um approach

Sendo declarativo ele nos permite definir a relao entre objetos uma vez e saber

que eles permaneceram em sincronia

Este

ao inv

s de ter de especificar comportamentos para

.
,

um conceito poderoso

porque um sistema em tempo real tem muitos inputs que

podem todos mudar em momentos imprevis veis

Ao afirmar declarativamente como n

renderizamos HTML baseado em qualquer fonte de informao reativa com que nos

importamos

Meteor pode tomar conta do servio de monitorar essas fontes e

transparentemente cuidar do trabalho bagunado de manter a interface do usurio

atualizada

Tudo isso para dizer que ao inv

gente escrever

s de pensar sobre callbacks do

observe , o Meteor deixa a

http://pt.discovermeteor.com/pdf

105/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

<template name="postsList">
<ul>
{{#each posts}}
<li>{{title}}</li>
{{/each}}
</ul>
</template>

E ento pega nossa lista de postagens com

Template.postsList.helpers({
posts: function() {
return Posts.find();
}
});

Por trs das cortinas

o Meteor est armando callbacks do

observe()

para n

e re

desenhando seguimentos relevantes de HTML quando a informao reativa muda

MonitoramentodeDependnciasemMeteor:Computaes

Apesar do Meteor ser um framework reativo

aplicativo em Meteor

reativo

Se este fosse o caso

vez que qualquer coisa mudasse

digo

em tempo real

Ento

a reatividade

limitada a reas espec ficas do seu

s podemos chamar essas reas de computa

Em outras palavras

a computao

informao reativa

reativamente a ela

renderiza

digo que roda cada vez que uma das

por exemplo

voc

es

um bloco de c

fontes de informao reativa na qual ela depende muda

Note que voc

digo dentro de um

todo seu aplicativo rodaria de novo cada

e n

nem todo c

Se voc

uma varivel de Sesso

tem uma fonte de

e gostaria de responder

precisar configurar uma computao para tanto

geralmente no precisa fazer isso explicitamente porque o Meteor d s

es de cada template sua pr

pria computao

o que significa dizer que o c

).

digo

nos ajudantes de template e callbacks so reativos por padro

http://pt.discovermeteor.com/pdf

106/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Cada fonte de informao reativa monitora todas as computa

que poder inform las quando seu pr

invalidate()

prio valor mudar

Para tanto

ela chama a funo

na computao

Computa

es que a esto usando para

es so geralmente configuradas a simplesmente re avaliar seus conte

invalidation

e isto

).

o que ocorre nas computa

es do template

do template tamb

eficientemente

dos on

apesar que as computa

es

m fazem alguma mgica ao tentar renderizar a pgina o mais

Apesar que voc

on invalidation se voc

precisar

pode ter mais controle quanto ao que cada computao faz

na prtico isto no ser algo que voc

far com freq

ncia

ConfigurandoumaComputao

Agora que n

s entendemos a teoria por trs das computa

parecer desproporcionalmente fcil

para envolver um bloco de c

.
N

es

configurar uma de fato

Deps.autorun

s simplesmente usamos a funo

digo na computao e faz

lo reativo

Deps.autorun(function() {
console.log('There are ' + Posts.find().count() + ' posts');
});

, autorun

Por trs das cortinas

cria uma computao

fontes de informao na qual ela depende mudam

simples que simplesmente informa o n

e a configura para re avaliar quando as

.
N

s configuramos uma computao bem

mero de postagens para o console

J que

Posts.find() uma fonte de informao reativa, ela tomar conta de informar a

computao para re avaliar cada vez que o n

mero de postagens mudar

> Posts.insert({title: 'New Post'});


There are 4 posts.

O resultado em rede de tudo isso

reativa de uma forma bem natural

depend

que n

s podemos escrever c

digo que usa informao

sabendo que por trs das cortinas o sistema de

ncia toma conta de rodar novamente bem na hora certa

http://pt.discovermeteor.com/pdf

.
107/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

http://pt.discovermeteor.com/pdf

108/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

CriandoArtigos

s vimos como

banco de dados

fcil criar artigos atrav

s do console

usando a chamada

Posts.insert

ao

mas n

criar um novo artigo

Eventualmente

s no podemos esperar que nossos usurios abram o console para

,
n

s precisaremos construir alguma forma de interface do usurio para

permitir aos nossos usurios postar novos artigos no nosso aplicativo

ConstruindoumaNovaPginadeArtigo

s comeamos por definir a rota para a nossa nova pgina

Router.configure({
layoutTemplate: 'layout',
loadingTemplate: 'loading',
waitOn: function() { return Meteor.subscribe('posts'); }
});
Router.map(function() {
this.route('postsList', {path: '/'});
this.route('postPage', {
path: '/posts/:_id',
data: function() { return Posts.findOne(this.params._id); }
});
this.route('postSubmit', {
path: '/submit'
});
});

lib router js

s estamos usando a funo

do template

data

postPage . Lembre

estar dispon vel ao

http://pt.discovermeteor.com/pdf

this

do roteador para configurar um contexto de informao

se que o quer que ponhamos nesse contexto de informao

de dentro dos ajudantes de template

109/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

AdicionandoumLinkaoCabealho

Com essa rota definida

,
n

s podemos agora adicionar um link a nossa pgina de envio no

nosso cabealho

<template name="header">
<header class="navbar">
<div class="navbar-inner">
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-col
lapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<a class="brand" href="{{pathFor 'postsList'}}">Microscope</a>
<div class="nav-collapse collapse">
<ul class="nav">
<li><a href="{{pathFor 'postSubmit'}}">New</a></li>
</ul>
<ul class="nav pull-right">
<li>{{loginButtons}}</li>
</ul>
</div>
</div>
</header>
</template>

client views includes header html

Configurar a nossa rota signifca que se o usurio procurar pela URL

mostrar o template

http://pt.discovermeteor.com/pdf

/submit , o Meteor

postSubmit . Ento vamos escrever esse template:

110/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

<template name="postSubmit">
<form class="main">
<div class="control-group">
<label class="control-label" for="url">URL</label>
<div class="controls">
<input name="url" type="text" value="" placeholder="Your URL"/>
</div>
</div>
<div class="control-group">
<label class="control-label" for="title">Title</label>
<div class="controls">
<input name="title" type="text" value="" placeholder="Name your
post"/>
</div>
</div>
<div class="control-group">
<label class="control-label" for="message">Message</label>
<div class="controls">
<textarea name="message" type="text" value=""/>
</div>
</div>
<div class="control-group">
<div class="controls">
<input type="submit" value="Submit" class="btn btn-primary"/>
</div>
</div>
</form>
</template>

/ _

client views posts post

Note

isto

Bootstrap

submit html

um monte de marcao

mas ela simplesmente adv

Apesar de apenas os elementos de formulrio serem essenciais

ajudar o nosso aplicativo a parecer um pouco melhor

assim

m de se usar o Twitter

a marcao extra

Agora ele dever se parecer com algo

http://pt.discovermeteor.com/pdf

111/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Thepostsubmitform

Este

um simples formulrio

.
N

s no precisamos nos preocupar com a ao para ele

j que

s estaremos interceptando eventos de envio no formulrio e atualizando a informao via

JavaScript

No faz sentido prover um plano reserva sem ser em JS quando se considera que

um aplicativo em Meteor

).

completamente no funcional quando o JavaScript est

desativado

CriandoArtigos

Vamos ligar um manuseador de evento ao evento

evento

submit

ao inv

s de digamos um evento

maneiras poss ves de envio

http://pt.discovermeteor.com/pdf

submit
click

do formulrio

),

no boto

melhor usar o

j que ele cobrir todas

).

tais como apertar enter no campo da URL por exemplo

112/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Template.postSubmit.events({
'submit form': function(e) {
e.preventDefault();
var post = {
url: $(e.target).find('[name=url]').val(),
title: $(e.target).find('[name=title]').val(),
message: $(e.target).find('[name=message]').val()
}

}
});

post._id = Posts.insert(post);
Router.go('postPage', post);

/ _

client views posts post

submit js

Commit71

Added a submit post page and linked to it in the header

Ver no GitHub

Lanar Instncia

Esta funo usa jQuery para analisar os valores dos vrios campos do formulrio

novo objeto artigo com os resultados

argumento do

event

.
N

e povoar o

preventDefault

s precisamos assegurar que n

no

do nosso manuseador para garantir que o navegador no v adiante e

tente enviar o formulrio

Finalmente

s podemos redirecionar a nossa nova pgina do artigo

numa coleo retorna a

funo

go()

id

insert()

gerada para o objeto que foi inserido no banco de dados

do Roteador usar para construir a URL para n

O resultado em rede

A funo

que o usurio aperta enviar

o artigo

a qual a

s navegarmos at

criado

e o usurio

instantaneamente levado pgina de discusso para este novo artigo

AdicionandoAlgumaSegurana

http://pt.discovermeteor.com/pdf

113/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Criar artigos est todo certo

mas n

s no queremos permitir que visitantes aleat

faam

s queremos que eles precisem estar logados para tanto

Claro

rios o

,
n

s podemos

comear escondendo dos usurios no logados o formulrio de novo artigo

Mesmo assim

um

usurio poderia concebivelmente criar um artigo no console do navegador sem estar logado

s no queremos isso

Agradecidamente a segurana de informao est inserida diretamente nas cole

a questo

que voc

que ela fica desligada por padro quando voc

cria um novo projeto

es Meteor

Isso permite

comece facilmente e construa seu aplicativo deixando a parte chata para mais tarde

Nosso aplicativo no precisa mais de rodinhas

- !

ento vamos tir las

insecure :

pacote

s removeremos o

$ meteor remove insecure

Terminal

Ap

s o faz

lo

noc

notar que o formulrio de artigo no funciona mais

insecure , inseres do lado do cliente na coleo posts

pacote

precisamos ou dar regras expl citas ao Meteor sobre quando

artigos

ou fazer todas nossas inser

Isto

porque sem o

no so mais permitidas

.
N

OK para um cliente inserir

es de artigo pelo lado do servidor

PermitindoInseresdeArtigo

Para comear

,
n

s mostraremos como permitir inser

deixar nosso formulrio funcionando de novo

terminaremos com uma t

cnica diferente

es de artigos pelo lado do cliente para

Como de costume

mas por hora

s eventualmente

o seguinte far as coisas funcionarem

de novo

http://pt.discovermeteor.com/pdf

114/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Posts = new Meteor.Collection('posts');


Posts.allow({
insert: function(userId, doc) {
// only allow posting if you are logged in
return !! userId;
}
});

collections posts js

Commit72
Removed insecure

and allowed certain writes to posts

Ver no GitHub

s chamamos

Lanar Instncia

Posts.allow , que diz ao Meteor

este

os clientes esto permitidos a fazer coisas coleo

dizendo

userId

retorna

clientes t

um conjunto de circunstncias onde

Posts . Neste caso, ns estamos

passada s chamadas

),

se nenhum usurio estiver logado

o que

de usurios so amarradas ao centro do Meteor

allow

quase sempre

.
til

s podemos contar com a

userId .

m permisso de inserir artigos desde que eles tenham uma

do usurio fazendo a modificao

null

and

deny

ou

E como as contas

userId

estar

sempre correta

s conseguimos garantir que voc

deslogar e criar um artigo

http://pt.discovermeteor.com/pdf

voc

precisar estar logado para criar um artigo

Tente

deve ver isto no console

115/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Insertfailed:Accessdenied

Entretanto

,
n

s ainda temos de lidar com algumas quest

es

Usurios no logados ainda conseguem alcanar o formulrio de criao de artigo

O artigo no est ligado ao usurio de forma alguma

).

e no h c

digo no servidor que

garanta isso

ltiplos artigos podem ser criados que apontem para a mesma URL

Vamos consertar esses problemas

ProtegendooAcessoaoFormulriodeNovoArtigo

Vamos comear prevenindo usurios no logados de ver o formulrio de envio de artigo

faremos isso no n vel do roteador

.
N

definindo um gancho de rota

Um gancho intercepta um processo de roteamento e potencialmente muda a ao que o

roteador toma

Voc

permitir que voc

pode pens lo como um segurana que checa suas credenciais antes de

entre

http://pt.discovermeteor.com/pdf

).

ou te recusar

116/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

O que n

s precisamos fazer

renderizar o template

checar se o usurio est logado

accessDenied

ao inv

e se eles no estiverem

s do esperado template

paramos o roteador de fazer qualquer outra coisa

).

postSubmit

(
n

s ento

Vamos modificar o router js para tanto

Router.configure({
layoutTemplate: 'layout'
});
Router.map(function() {
this.route('postsList', {path: '/'});
this.route('postPage', {
path: '/posts/:_id',
data: function() { return Posts.findOne(this.params._id); }
});
this.route('postSubmit', {
path: '/submit'
});
});
var requireLogin = function() {
if (! Meteor.user()) {
this.render('accessDenied');
this.stop();
}
}
Router.before(requireLogin, {only: 'postSubmit'});

lib router js

s tamb

m criamos o template da pgina acesso negado

<template name="accessDenied">
<div class="alert alert-error">You can't get here! Please log in.</div>
</template>

client views includes access

http://pt.discovermeteor.com/pdf

denied html

117/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Commit73

Denied access to new posts page when not logged in

Ver no GitHub

Se voc

tentar ir a http

//

Lanar Instncia

:3000

localhost

submit

sem estar logado

voc

deve ver isto

Theaccessdeniedtemplate

A coisa legal quanto a ganchos de roteamento

que eles so reativos

podemos ser declarativos e no precisamos pensar em callbacks

usurio loga

Quando o estado de log in do usurio muda

muda instantaneamente de

escrever nenhum c

Logue

accessDenied

para

Isso signfica que n

ou similares

quando o

a pgina de template do Roteador

postSubmit

sem que n

s precisemos

digo expl cito para tanto

e ento tente atualizar a pgina

Voc

pode ver s vezes o template negado piscar por

um breve momento antes da pgina de envio de artigo aparecer

Meteor comea renderizando templates o mais cedo poss vel

servidor e checar se o usurio atualmente

http://pt.discovermeteor.com/pdf

A razo para tanto

que o

antes de conversar com o

armazenado no banco local do navegador

sequer

118/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

existe

Para evitar este problema

voc

que

uma classe de problemas comum que voc

),

lidar com os detalhes da lat

ncia entre cliente e servidor

tela de loading pelo breve momento em que n

ver mais quando

s apenas mostraremos uma

s esperamos para ver se o usurio tem acesso

ou no

At

mesmo porque neste estgio n

corretas

e n

s no sabemos se o usrio tem as credenciais log in

s no podemos mostrar tanto

accessDenied

ou o template

postSubmit

at

que saibamos

Ento n

s modificamos no nosso gancho para usar o nosso template loading embora

Meteor.loggingIn()

seja verdadeiro

Router.map(function() {
this.route('postsList', {path: '/'});
this.route('postPage', {
path: '/posts/:_id',
data: function() { return Posts.findOne(this.params._id); }
});
this.route('postSubmit', {
path: '/submit'
});
});
var requireLogin = function() {
if (! Meteor.user()) {
if (Meteor.loggingIn())
this.render(this.loadingTemplate);
else
this.render('accessDenied');

this.stop();

Router.before(requireLogin, {only: 'postSubmit'});

lib router js

http://pt.discovermeteor.com/pdf

119/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Commit74

Show a loading screen while waiting to login

Ver no GitHub

Lanar Instncia

EscondendooLink

A maneira mais fcil de prevenir que os usurios cheguem a esta pgina por engano quando

eles no esto logados

esconder o link deles

s podemos fazer isso bem facilmente

<ul class="nav">
{{#if currentUser}}<li><a href="{{pathFor 'postSubmit'}}">Submit Post</a><
/li>{{/if}}
</ul>

client views includes header html

Commit75

Only show submit post link if logged in

Ver no GitHub

O ajudante

currentUser

nos

Lanar Instncia

provido pelo pacote

accounts

o handlebar equivalent de

Meteor.user() . J que reativo, o link ir aparecer ou desaparecer ao voc logar e deslogar


do aplicativo

MtodoMeteor:AbstraoeSeguranaMelhores

s conseguimos proteger o acesso pgina de novo artigo de usurio no logados

que tais usurios criem artigos mesmo que eles trapaceiem e usem o console

mais algumas coisas que n

http://pt.discovermeteor.com/pdf

s precisamos tomar conta

Por

e negar

m ainda h

:
120/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Timestamping os artigos

Assegurar que uma mesma URL no seja publicada mais que uma vez

Adicionar detalhes sobre o autor do artigo

Voc

ID

username

..

etc

talvez esteja pensando que n

s podemos fazer tudo isso no nosso manuseador de

submit , entretanto, ns rapidamente encontraramos uma srie de problemas:

evento

Para a timestamp

usurio

s ter amos de contar com a corretude do tempo do computador do

o qual nem sempre ser o caso

Clientes no saberam de todas as URLs j publicadas no site

artigos que eles podem ver atualmente

),

mais tarde

Finalmente

s veremos como isso funciona exatamente

ento no h como garantir originalidade de URL pelo lado do cliente

apesar que n

cliente

Eles apenas sabero dos

s poder amos adicionar detalhes de usurio pelo lado do

s no poder amos garantir sua acurcia

o que poderia abrir o nosso

aplicativo para os usurios trapaceando pelo console do navegador

Por todas essas raz

es

melhor manter nossos manuseadores de evento simples e

estivermos fazendo mais do que inser

es e atualiza

es bsicas coleo

se n

usemos um

todo

Um M

todo Meteor

uma funo do lado do servidor que

temos alguma familiaridade com elas

update

remove

Vamos voltar a

da

Coleo

alis

todos

chamada pelo lado do cliente

por trs das cortinas

so todos M

as fun

es

insert ,

Vamos ver como criar o nosso pr

prio

post_submit.js . Ao invs de inserir diretamente na coleo Posts , ns

chamaremos um M

todo chamado

http://pt.discovermeteor.com/pdf

post :

121/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Template.postSubmit.events({
'submit form': function(e) {
e.preventDefault();
var post = {
url: $(e.target).find('[name=url]').val(),
title: $(e.target).find('[name=title]').val(),
message: $(e.target).find('[name=message]').val()
}
Meteor.call('post', post, function(error, id) {
if (error)
return alert(error.reason);

}
});

Router.go('postPage', {_id: id});


});

/ _

client views posts post

Meteor.call

A funo

submit js

prover argumentos chamada

),

formulrio

todo nomeado pelo seu primeiro argumento

neste caso

o objeto

e finalmente anexar um callback

servidor estiver finalizado

problema

chama um M

post

que n

Voc

s constru mos atrav

o qual executar quando o M

pode

s do

todo do lado do

Aqui n

s simplesmente alertamos o usurio se houve algum

ou redirecionamos o usurio recentemente criada pgina de discusso do artigo

caso contrrio

s definimos o M

allow()

do

todo no nosso arquivo

posts.js

j que o M

so executados no servidor

http://pt.discovermeteor.com/pdf

collections/posts.js . Ns removeremos o bloco

todo Meteor ignora eles mesmo

Lembre se que M

todos

ento o Meteor assume que eles sejam confiveis

122/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Posts = new Meteor.Collection('posts');


Meteor.methods({
post: function(postAttributes) {
var user = Meteor.user(),
postWithSameLink = Posts.findOne({url: postAttributes.url});

// ensure the user is logged in


if (!user)
throw new Meteor.Error(401, "You need to login to post new stories");
// ensure the post has a title
if (!postAttributes.title)
throw new Meteor.Error(422, 'Please fill in a headline');
// check that there are no previous posts with the same link
if (postAttributes.url && postWithSameLink) {
throw new Meteor.Error(302,
'This link has already been posted',
postWithSameLink._id);
}
// pick out the whitelisted keys
var post = _.extend(_.pick(postAttributes, 'url', 'title', 'message'), {
userId: user._id,
author: user.username,
submitted: new Date().getTime()
});
var postId = Posts.insert(post);
}
});

return postId;

collections posts js

Commit76

Use a method to submit the post

Ver no GitHub

Este M

todo

um pouco complicado

http://pt.discovermeteor.com/pdf

Lanar Instncia

mas felizmente voc

pode seguir adiante

123/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Primeiro

existe

s definimos nossa varivel

Ento

,
n

user

e checamos se o artigo com o mesmo link j

s checamos para ver se o usurio est logado

alert

eventualmente ser

ado pelo navegador

jogando um erro

caso contrrio

o qual

s tamb

m fazemos

alguma validao simples do objeto artigo para garantir que os nossos artigos tenham t tulo

Em seguida

se h outro artigo com a mesma URL

significa redirecionar

A classe

num

e o

Error

,
n

dizendo ao usurio que n

do Meteor recebe tr

s dever amos ir e ver este artigo pr

s argumentos

302

s podemos lanar um erro

O primeiro

( error )

o qual

vio

ser o c

digo

302 , o segundo reason uma pequena explicao legvel por humanos do erro,

rico

ltimo

( details )
,

No nosso caso

pode ser qualquer informao

til adicional

s usaremos este terceiro argumento para passar a ID do artigo que n

acabamos de encontrar

usurio para o artigo pr

Spoiler alert

existente

assim como o tempo atual

,
n

),

s usaremos isso mais tarde para redirecionar o

s agarraremos os campos que n

s queremos inserir

para garantir que o usurio que esteja chamando este M

falsa no nosso banco de dados

Se todas essas checagens passarem

Finalmente

todo no possa por informao

e incluiremos alguma informao sobre o usurio que envia

ao artigo

s inserimos o artigo

e retornamos a

id

do novo artigo ao usurio

OrganizandoArtigos

Agora que n

s temos data de envio em todos os nossos artigos

estejam organizados usando esse atributo

do Mongo

faz sentido assegurar que eles

Para tanto

s podemos usar o operador

que espera um objeto feito de chaves pelas quais organizar

de forma ascendente ou descendente

http://pt.discovermeteor.com/pdf

sort

e um sinal indicando se

124/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Template.postsList.helpers({
posts: function() {
return Posts.find({}, {sort: {submitted: -1}});
}
});

client views posts posts

list js

Commit77

Sort posts by submitted timestamp

Ver no GitHub

Levou um pouco de trabalho

mas n

nossos usurios adicionar conte

Lanar Instncia

s finalmente temos uma interface do usurio para deixar

do seguramente ao nosso aplicativo

Mas qualquer aplicativo que permite ao usurio criar conte

edit lo e delet lo

do tamb

Sobre isso que se tratar o cap tulo Editando Artigos

http://pt.discovermeteor.com/pdf

m precisa deix los

125/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

CompensaodeLatncia

No

7.5

SIDEBAR

ltimo cap tulo

s introduzimos um novo conceito no mundo Meteor

:
M

todos

Withoutlatencycompensation

Um M

todo Meteor

forma estruturada

uma forma de executar uma s

No nosso exemplo

rie de comandos no servidor de uma

,
n

s usamos um M

todo porque n

s quer amos ter

certeza que os novos artigos estariam marcados com o nome do autor e id assim como o

tempo atual do servidor

Entretanto

problema

aleat

se o Meteor executasse M

Considere a seguinte seq

rios selecionados por raz

+0

ms

todos da forma mais bsica

ncia de eventos

(
):

note

s ter amos um

as timestamps so valores

es apenas ilustrativas

O usurio clica no boto de enviar e o navegador dispara uma chamada a um

http://pt.discovermeteor.com/pdf

126/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

todo

+200
+500

ms

ms

O servidor faz mudanas ao banco de dados Mongo

O cliente recebe essas mudanas

Se esta fosse a forma como o Meteor operasse

tais a

es e ver os resultados

pr

ximo se est do servidor

).

e atualiza a UI para reflet

las

ento haveria um pequeno lag entre efetuar

esse lag sendo mais ou menos percept vel dependendo de quo

s no podemos ter isso numa aplicativo web moderno

CompensaodeLatncia

http://pt.discovermeteor.com/pdf

127/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Withlatencycompensation

Para evitar problemas

Quando n

diret

rio

cliente

o Meteor introduz um conceito chamado Compensao de Lat

s definimos nosso M

todo

ncia

post , ns o colocamos dentro de um arquivo no

collections/ . Isto significa que ele est disponvel tanto no servidor

quanto no

e rodar em ambos ao mesmo tempo

Quando voc

faz uma chamada a um M

http://pt.discovermeteor.com/pdf

todo

o cliente envia uma chamada ao servidor

mas

128/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

tamb

m simultaneamente simula a ao do M

de trabalho agora se torna

+0
+0

ms

ms

todo nas cole

es do cliente

Ento nosso fluxo

O cliente simula a ao da chamada ao M

todo nas cole

todo

es do cliente e muda a

las

O servidor faz mudanas ao banco de dados Mongo

ms

O cliente recebe essas mudanas e desfaz suas mudanas simuladas

ms

as pelas mudanas do servidor

UI refletiro isso

as quais so geralmente as mesmas

Isto resulta no usurio ver mudanas instantaneamente

retorna alguns momentos mais tarde

documentos can

).

trocando

As mundanas na

Quando a responda do servidor

pode ou no haver mudanas notveis ao passo que os

nicos do servidor chegam pela conexo

O usurio clica no boto enviar e o navegador dispara uma chamada ao M

UI para reflet

+200
+500

Algo a se aprender com isto

que

s devemos tentar ter certeza que n

s simulamos os documentos reais o mais

veridicamente

ObservandoaCompensaodeLatncia

s podemos fazer uma pequena mudana chamada ao M

ao

Para tanto

s usaremos

isSimulation

invocado como um stub

paralelo

para ver isso em

enquanto o M


real

adicionamos a string

http://pt.discovermeteor.com/pdf

(client)

todo est sendo atualmente

uma simulao de M

todo que roda no cliente em

est rodando no servidor

s perguntamos ao Meteor se o c

adicionamos a string

Um stub

todo

futures

todo

para perguntar ao Meteor se o M

Ento n

post

s faremos alguma programao avanada com o pacote npm

para retardar a insero de objetos no nosso M

todo

digo est sendo executado no cliente

ao final do t tulo do nosso post

Caso contrrio

Se sim

,
n

,
n

(server) :

129/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Meteor.methods({
post: function(postAttributes) {
// []

// pick out the whitelisted keys


var post = _.extend(_.pick(postAttributes, 'url', 'message'), {
title: postAttributes.title + (this.isSimulation ? '(client)' : '(serv
er)'),
userId: user._id,
author: user.username,
submitted: new Date().getTime()
});
// wait for 5 seconds
if (! this.isSimulation) {
var Future = Npm.require('fibers/future');
var future = new Future();
Meteor.setTimeout(function() {
future.return();
}, 5 * 1000);
future.wait();
}
var postId = Posts.insert(post);
}
});

return postId;

collections posts js

Note

caso voc

esteja se perguntando

invocao de M

todo que prov

this

em

this.isSimulation um objeto de

acesso a vrias variveis

teis

Como exatamente Futures funciona est fora do escopo deste livro

dissemos ao Meteor para esperar

mas n

s basicamente

segunos antes de tentar inserir na nossa coleo do

servidor

s tamb

m garantiremos que o envio redirecione diretamente para a list de artigos

http://pt.discovermeteor.com/pdf

130/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Template.postSubmit.events({
'submit form': function(event) {
event.preventDefault();
var post = {
url: $(event.target).find('[name=url]').val(),
title: $(event.target).find('[name=title]').val(),
message: $(event.target).find('[name=message]').val()
}

}
});

Meteor.call('post', post, function(error, id) {


if (error)
return alert(error.reason);
});
Router.go('postsList');

/ _

client views posts post

submit js

Commit751

Demonstrate the order that posts appear using a sleep

Ver no GitHub

Se n

s criamos um artigo agora

um artigo

o GitHub

):

inserido como

http://pt.discovermeteor.com/pdf

Lanar Instncia

,
n

s vemos a compensao de lat

(cliente)

em seu t tulo

ncia claramente

o primeiro artigo da lista

Primeiro

linkando para

131/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Ourpostasfirststoredintheclientcollection

Ento

cinco segundos mais tarde

inserido pelo servidor

ele

claramente substitu do pelo documento real que foi

Ourpostoncetheclientreceivestheupdatefromtheservercollection

MtodonaColeodoCliente
http://pt.discovermeteor.com/pdf

132/261

1/8/2015

Voc

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

pode pensar que M

todos so complicados depois disso

bem simples

s j vimos tr

insert , update

Quando voc

definindo tr

palavras

um M

1.

s M

todos bem simples

os M

todos

quando voc

'posts' , voc est implicitamente

: posts/insert , posts/update
chama

Posts.insert()

posts/delete . Em outras

na coleo do cliente

todo de lat

todos de mutao de Coleo

remove .

define uma coleo no servidor chamada

s M

mas na real eles podem ser

voc

est chamando

ncia compensada que faz duas coisas

Checa para ver se n

s podemos fazer a mutao chamando as callbacks

).

allow

deny

entretanto isto no precisa ocorrer na simulao

2.

De fato opera a modificao ao armazenamento de informao subjacente

MtodoschamandoMtodos

Se voc

est acompanhando

chamando outro M

todo

voc

pode ter percebido que o nosso M

( posts/insert )

quando n

todo

post

s inserimos nosso post

est

Como isso

funciona

Quando a simulao

simulao do

verso do M

insert

ento n

, insert

post

do lado do servidor

j que n

est rodando

),

s inserimos na nossa coleo do cliente

chamamos o real

servidor do

todo do lado do cliente

s rodamos a

mas n

s no

s esperamos que a verso do lado do

far isso

Consequentemente

quando o M

todo

post

do lado do servidor chama

necessidade de se preocupar quanto simulao

http://pt.discovermeteor.com/pdf

insert

no h

e a insero ocorre suavemente

133/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

EditandoArtigos

Agora que j conseguimos criar artigos

Dado que o c

o pr

digo de UI desta funcionalidade

conseguir edita los e remove los

bastante simples

falar sobre como Meteor gere permiss

ximo passo

esta

uma boa altura para

es de utilizadores

Vamos primeiro configurar o nosso roteador

Primeiro vamos adicionar uma rota para aceder

pgina de edio do artigo e vamos definir o seu contexto de dados

Router.configure({
layoutTemplate: 'layout'
});
Router.map(function() {
this.route('postsList', {path: '/'});
this.route('postPage', {
path: '/posts/:_id',
data: function() { return Posts.findOne(this.params._id); }
});
this.route('postEdit', {
path: '/posts/:_id/edit',
data: function() { return Posts.findOne(this.params._id); }
});
this.route('postSubmit', {
path: '/submit'
});
});
var requireLogin = function() {
if (! Meteor.user()) {
if (Meteor.loggingIn())
this.render('loading')
else
this.render('accessDenied');

this.stop();

Router.before(requireLogin, {only: 'postSubmit'});


http://pt.discovermeteor.com/pdf

134/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

lib router js

OTemplateDeEdiodeArtigos

Podemo nos focar agora no template

standard

O nosso template

postEdit

vai ser um formulrio

<template name="postEdit">
<form class="main">
<div class="control-group">
<label class="control-label" for="url">URL</label>
<div class="controls">
<input name="url" type="text" value="{{url}}" placeholder="Your
URL"/>
</div>
</div>
<div class="control-group">
<label class="control-label" for="title">Title</label>
<div class="controls">
<input name="title" type="text" value="{{title}}" placeholder="N
ame your post"/>
</div>
</div>
<div class="control-group">
<div class="controls">
<input type="submit" value="Submit" class="btn btn-primary submi
t"/>
</div>
</div>
<hr/>
<div class="control-group">
<div class="controls">
<a class="btn btn-danger delete" href="#">Delete post</a>
</div>
</div>
</form>
</template>

/ _

client views posts post

E aqui est o gestor

edit html

post_edit.js

http://pt.discovermeteor.com/pdf

que acompanha o template

135/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Template.postEdit.events({
'submit form': function(e) {
e.preventDefault();
var currentPostId = this._id;
var postProperties = {
url: $(e.target).find('[name=url]').val(),
title: $(e.target).find('[name=title]').val()
}
Posts.update(currentPostId, {$set: postProperties}, function(error) {
if (error) {
// display the error to the user
alert(error.reason);
} else {
Router.go('postPage', {_id: currentPostId});
}
});
},
'click .delete': function(e) {
e.preventDefault();
if (confirm("Delete this post?")) {
var currentPostId = this._id;
Posts.remove(currentPostId);
Router.go('postsList');
}

}
});

/ _

client views posts post

edit js

Por esta altura a maioria do c

digo deve parecer familiar

Primeiro

temos o nosso ajudante de

template que carrega o artigo atual e passa o ao template

Depois

temos duas callbacks de eventos do template

do formulrio

e outra para o

A callback do apagar

muito simples

utilizador para confirmar

do Template

suprimir o evento de click por omisso

submit

submeter

no link de apagar

Caso isso acontea

apaga o artigo

http://pt.discovermeteor.com/pdf

click

uma para o evento

e pedir ao

obt

m o ID do artigo atual do contexto de dados

e finalmente redireciona o utilizador para a pgina inicial

.
136/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

A callback de edio

ligeiramente maior

mas no muito mais complicada

suprimir o evento por omisso e de ir buscar o artigo atual

lemos os novos valores dos

campos do formulrio da pgina e guardamo los num objecto

).

Depois de

postProperties

propriedades do artigo

Depois passamos este objecto para o M

todo de Meteor

a callback que ou mostra um erro se a atualizao falhou

Collection.update() , e utilizamos

ou envia o utilizador de volta para a

pgina do artigo caso a atualizao tenha sido feita com sucesso

AdicionandoLinks

Devemos ainda adicionar links de edio aos nossos artigos para que os utilizadores tenham

uma forma de aceder pgina de edio de artigos

<template name="postItem">
<div class="post">
<div class="post-content">
<h3><a href="{{url}}">{{title}}</a><span>{{domain}}</span></h3>
<p>
submitted by {{author}}
{{#if ownPost}}<a href="{{pathFor 'postEdit'}}">Edit</a>{{/if}}
</p>
</div>
<a href="{{pathFor 'postPage'}}" class="discuss btn">Discuss</a>
</div>
</template>

/ _

client views posts post

Naturalmente

item html

no queremos mostrar links de edio para o formulrio de outra pessoa

aqui que o ajudante

ownPost

http://pt.discovermeteor.com/pdf

entra

137/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Template.postItem.helpers({
ownPost: function() {
return this.userId == Meteor.userId();
},
domain: function() {
var a = document.createElement('a');
a.href = this.url;
return a.hostname;
}
});

/ _

client views posts post

item js

Formulriodeediodeartigo.

Commit81
Formulrio de edio de artigos adicionado

Ver no GitHub

Lanar Instncia

O nosso formulrio de edio de artigos est com bom aspeto

nada

O que

mas ainda no

poss vel editar

que se passa

http://pt.discovermeteor.com/pdf

138/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

DefinindoPermisses
insecure , todas as modificaes feitas do

Dado que anteriormente removemos o pacote

lado do cliente esto a ser recusadas

Para corrigir isto

permissions.js

.
.

vamos definir alguma regras de permiss

dentro de

carregada primeiro

es

Primeiro

crie um novo ficheiro

lib . Isto faz com que a nossa lgica de permisses seja

e que esteja dispon vel em ambos os ambientes

):

// check that the userId specified owns the documents


ownsDocument = function(userId, doc) {
return doc && doc.userId === userId;
}

lib permissions js

No capitulo Criando Artigos

,
n

apenas a inserir novos artigos atrav

ignora o

s vimo nos livres dos M

s de um M

todos

allow()

todo de servidor

allow() .

que de qualquer forma

Mas agora que estamos a atualizar e apagar artigos a partir do cliente

posts.js

e adicionar este bloco

porque estvamos

vamos voltar ao

allow() :

Posts = new Meteor.Collection('posts');


Posts.allow({
update: ownsDocument,
remove: ownsDocument
});
Meteor.methods({
...

collections posts js

http://pt.discovermeteor.com/pdf

139/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Commit82

Permisso bsica que verifica o dono do artigo adicionada

Ver no GitHub

Lanar Instncia

LimitandoEdies

porque pode editar os seus pr

propriedade

no quer dizer que deva poder editar qualquer

Por exemplo

prios artigos

s no queremos que os utilizadores sejam capazes de criar um

artigo e depois associ lo a outro utilizador

A callback

deny()

do Meteor

utilizada para garantir que apenas campos espec ficos podem

ser atualizados

Posts = new Meteor.Collection('posts');


Posts.allow({
update: ownsDocument,
remove: ownsDocument
});
Posts.deny({
update: function(userId, post, fieldNames) {
// may only edit the following two fields:
return (_.without(fieldNames, 'url', 'title').length > 0);
}
});

collections posts js

Commit83
Permitir que apenas certos campos do artigo possam ser al

Ver no GitHub

http://pt.discovermeteor.com/pdf

Lanar Instncia

140/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Estamos a pegar na lista

todo

without()
url

que no so

fieldNames

m os campos a serem modificados e usamos o

do Underscore para devolver uma sub lista contendo apenas os campos

title .

ou

Se tudo est normal

essa lista deve estar vazia e o seu tamanho deve ser

tentar alguma coisa manhosa

true

que cont

o tamanho dessa lista ser

).

ou mais

0.

Se alguem est a

e a callback vai devolver

impedindo assim a atualizao

ChamadasaMtodosvsManipulaodeDadosNoLadodoCliente

Para criar artigos

apagar

estamos a utilizar o M

update

estamos a chamar

acesso usando

Quando

allow

todo

remove

post , enquanto que para os editar e


diretamente no cliente e limitamos o

deny .

adequado usar um e no o outro

Quando as coisas so relativamente simples e as regras podem ser exprimidas por

allow

deny , normalmente mais simples fazer as coisas diretamente no cliente.

Manipular a base de dados diretamente a partir do cliente cria uma percepo de

imediato

e pode fazer com que a experi

ncia de utilizao seja melhor desde que os

casos de erro sejam tratados adequadamente

dizendo que a operao afinal falhou

No entanto

).

a partir do momento em que

fora do controlo do utilizador

Quando

isto

quando o servidor responde

necessrio fazer coisas que devem estar

tais como dar timestamps a novos artigos ou associar

),

um artigo ao utilizador correto

Chamadas a M

provavelmente melhor usar um M

todo

todos tamb

.
:

m so mais adequadas em alguns outros casos

preciso saber ou

preciso devolver valores atrav

s de uma callback

em vez de esperar que a reatividade e sincronizao propaguem as altera

Para opera

es de base de dados pesadas que implicariam enviar uma coleo

grande para o cliente

Para sumarizar ou agregar dados

http://pt.discovermeteor.com/pdf

es

por exemplo

contar

dias

).

somas

141/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

http://pt.discovermeteor.com/pdf

142/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

AllowandDeny

8.5

SIDEBAR

O sistema de segurana do Meteor nos permite controlar modifica

precisarmos definir M

todos toda vez que n

es ao banco de dados sem

s queremos fazer mudanas

Por n

s necessitarmos fazer tarefas auxiliares como decorar o post com propriedades extras e

tomar uma ao especial quando o URL do post j ter sido postada

usar um M

todo

post

espec fico fazia bastante sentido ao se criar um post

Por outro lado

posts

s no precisamos realmente criar novos M

todos para atualizar e deletar

.
N

s apenas precisamos checar se o usurio tem permisso para fazer tais a

foi feito pelas callbacks

allow

,
es

e isto

deny .

Usar estas callbacks nos permite sermos mais declarativos quanto s modifica

de dados

e dizer que tipo de atualiza

sistema de contas

um b

es podem ser feitas

es ao banco

O fato delas se integrarem ao

nus adicional

Callbacksmltiplas

s podemos definir quantas callbacks

menos uma delas retorne

true

allow

),

ele no permitir o insert

no importa se

do c

encontrar uma que retorne true

e retornar um erro

403

como cada callback

insert

bem sucedido

deny insert

http://pt.discovermeteor.com/pdf

digo do aplicativo do lado do

insert

Se ele no encontrar nenhuma

deny . Se

true , a mudana ser cancelada e um 403

significa que para um

Ento quando

para o cliente

s podemos definir uma ou mais callbacks

callbacks retornar

s precisamos que pelo

,
n

o servidor ir em resposta chamar quaisquer checagens de

permitidas que ele puder at

Similarmente

para a dada mudana que est ocorrendo

Posts.insert chamado no navegador


cliente ou do console

quanto necessrias

ser retornado

uma ou mais callback

sero executadas

qualquer uma dessas

A l

gica disto

allow insert

assim

143/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Note:n/estandsforNotExecuted

Em outras palavras

Meteor comea a lista de callback primeiro com

deny , ento com

allow , e executa cada callback at que uma delas retorne true .

Um exemplo prtico deste padro poderia ser ter duas callbacks

o post pertence ao usurio atual

administrativos

qualquer post

allow() , uma que checa se

e a segunda que checa se o usurio atual tem direitos

Se o usurio atual

um administrador

isto garante que ele poder atualizar

j que pelo menos uma dessas callbacks retornar true

CompensaodeLatncia

Lembre que M

compensada

todos de mutao do banco de dados

assim como qualquer outro M

post que no pertence a voc

atrav

todo

s do console

tais como

Por exemplo

voc

no

se voc

tem sua lat

tentar deletar um

mas ento re aparece assim

um problema quando acionado pelo console

at

mesmo porque se os usurios estiverem tentando bagunar com informao no console

).

realmente um problema seu o que acontece no navegador deles

assegurar que isto no acontea na sua interface do usurio

cuidado para assegurar que voc

documentos que eles no t

http://pt.discovermeteor.com/pdf

ncia

de fato o documento no foi deletado

Claro que este comportamento no

ver que o post brevemente

desaparece ao passo que sua coleo local perde o documento

que o servidor informa que

.update()

Entretanto

Por exemplo

voc

voc

no

precisa

precisa tomar

no est mostrando aos usurios bot

es de deletar para

m permisso para tanto

144/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Felizmente

j que voc

por exemplo

e p

voc

pode compartilhar c

digo de permisso entre o cliente e o servidor

canDeletePost(user, post)

poderia escrever uma funo de biblioteca

la no diret

extra

/lib , fazer isto normalmente no requer muito cdigo

rio compartilhado

Permissesdoladodoservidor

Lembre que o sistema de permiss

iniciadas no cliente

No servidor

es se refere apenas s muta

o Meteor assume que todas opera

Isto signfica que se voc

tivesse que escrever um M

servidor que pudesse ser chamado do cliente

post

Ento voc

es do banco de dados

todo Meteor

deletePost

do lado do

qualquer um seria capaz de deletar qualquer

provavelmente no quer fazer isso a no ser que voc

do usurio dentro do M

es so permitidas

cheque as permiss

es

todo tamb

UsandoDenycomoumaCallback

Finalmente

um truque que voc

Por exemplo

voc

pode fazer com

deny us

pode conseguir uma timestamp

la como uma callbaclk

lastModified

com o c

.
onX

digo seguinte

Posts.deny({
update: function(userId, doc, fields, modifier) {
doc.lastModified = +(new Date());
return false;
},
transform: null
});

Como callbacks

deny

rodam para cada

update

bem sucedido

,
n

s sabemos que essa

callback rodar e poder fazer mudanas ao documento de uma forma estruturada

Admitidamente

usando um M

esta t

cnica

todo no lugar

ento voc

De qualquer forma

esperar que algum tipo de callback

http://pt.discovermeteor.com/pdf

tipo um hack

ainda

beforeUpdate

pode querer fazer atualiza

bom saber

es

e no futuro n

s podemos

esteja dispon vel

145/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

http://pt.discovermeteor.com/pdf

146/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Erros

alert()

Usar meramente o dilogo

um problema com o envio

s podemos fazer melhor

Ao inv

padro do navegador para avisar o usurio quando h

um pouco insatisfat

rio

e certamente no produz uma boa UX

vamos construir um mecanismo de reportagem de erro mais verstil que far melhor

o trabalho de dizer ao usurio o que est acontecendo sem interromper o fluxo

IntroduzindoColeesLocais

s implementaremos um simples sistema que rastrear quais erros um usurio viu e

mostrar os novos numa rea

flash

do site

Este padro UX

til quando n

s queremos

informar ao usurio que algo aconteceu sem interromper o workflow demasiadamente

O que n

s criaremos

similar as mensagems flash costumeiramente encontradas em

aplicativos com Ruby on Rails

mas

e sabe quando um usurio viu uma mensagem

Para comear

muito mais s

til pois

,
n

implementada do lado do cliente

s criamos uma coleo para armazenar nossos erros

Dado que os erros so

apenas relevantes para a sesso atual e no precisam ser persistentes de forma alguma

faremos algo novo

e criaremos uma coleo local

apenas no navegador

Isso significa que a coleo

Errors

existir

e no far nenhuma tentativa de sincronizar com o servidor

Para conseguir isto

s simplesmente criamos o error num arquivo apenas do cliente

nome da coleo configurado para

null . Ns criamos uma funo throwError

com o

que

simplesmente insere um error na nossa nova coleo local

// Local (client-only) collection


Errors = new Meteor.Collection(null);

client helpers errors js

http://pt.discovermeteor.com/pdf

147/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Agora que a coleo foi criada

s podemos adicionar uma funo

chamaremos para adicionar erros a ela

deny

ou

.
N

ou qualquer outra coisa assim

banco de dados Mongo

throwError

que n

s no precisamos nos preocupar quanto a

j que isto

allow

uma coleo local e no ser salva no

throwError = function(message) {
Errors.insert({message: message})
}

client helpers errors js

A vantagem de usar uma coleo local para armazenar os errors

ela

reativa

forma que n

significando que n

que

como todas cole

es

s podemos declarativamente mostrar os erros da mesma

s mostramos informao de qualquer outra coleo

Mostrandoerros

s vamos mostrar os erros no topo do nossos layout principal

<template name="layout">
<div class="container">
{{> header}}
{{> errors}}
<div id="main" class="row-fluid">
{{yield}}
</div>
</div>
</template>

client views application layout html

Vamos agora criar os templates

http://pt.discovermeteor.com/pdf

errors

error

em

errors.html :

148/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

<template name="errors">
<div class="errors row-fluid">
{{#each errors}}
{{> error}}
{{/each}}
</div>
</template>
<template name="error">
<div class="alert alert-error">
<button type="button" class="close" data-dismiss="alert">&times;</button
>
{{message}}
</div>
</template>

client views includes errors html

TemplatesGmeos
Voc

notar que n

s tentamos aderir conveno

se importa p

bem

um arquivo

r todos os nossos templates num

apesar que produziria um

Neste caso

s estamos pondo dois templates num mesmo arquivo

main.html

um template

mas at

onde o Meteor

).

bem confuso

j que ambos templates de error so bem curtos

s faremos uma

rio um pouco mais

agora

nico arquivo funciona igualmente

exceo e os poremos no mesmo arquivo para fazer nosso reposit

limpo

At

s apenas precisamos integrar nosso ajudante de template

e estaremos prontos para ir

Template.errors.helpers({
errors: function() {
return Errors.find();
}
});

client views includes errors js

http://pt.discovermeteor.com/pdf

149/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Commit91
Basic error reporting

Ver no GitHub

Lanar Instncia

Criandoerros

s agora sabemos como mostrar erros

vermos qualquer coisa

Erros prov

mas n

s ainda precisamos criar alguns antes de

m geralmente de usurios tentando enviar novo conte

ento n

s checaremos por erros na nossa callback de criao de artigo

,
do

e mostraremos uma

mensagem para qualquer erro que for levantado

Em adio

existe

),

se n

s pegarmos o erro

302

o qual indica que um artigo com a mesma URL j

s redirecionaremos o usurio para o artigo existente

artigo exitente do

error.details

terceiro argumento de

http://pt.discovermeteor.com/pdf

details

lembre se que n

da nossa classe

s obteremos o

s passamos o

Error

_id

no cap tulo

_id

do

do artigo como o

7.

150/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Template.postSubmit.events({
'submit form': function(e) {
e.preventDefault();
var post = {
url: $(e.target).find('[name=url]').val(),
title: $(e.target).find('[name=title]').val(),
message: $(e.target).find('[name=message]').val()
}
Meteor.call('post', post, function(error, id) {
if (error) {
// display the error to the user
throwError(error.reason);

}
});

if (error.error === 302)


Router.go('postPage', {_id: error.details})
} else {
Router.go('postPage', {_id: id});
}
});

/ _

client views posts post

submit js

Commit92
Actually use the error reporting

Ver no GitHub

Experimente

Lanar Instncia

tente criar um artigo e entre a URL

anexada a um artigo nos preenchimentos

http://pt.discovermeteor.com/pdf

voc

http://meteor.com . Como essa URL j est

pode ver

151/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Triggeringanerror

LimpandoErros

Agora voc

pode ter tentando clicar no boto de fechar do error

de ver o erro desaparecer

pgina

Se voc

o fez

apenas para logo mais ele reaparecer quando voc

voc

gostaria

ler uma nova

O que est acontecendo

O boto de fechar dispara o JavaScript embutido do Twitter Bootstrap

com o Meteor

error do DOM

Ento o que est acontecendo

mas no d coleo Meteor

assim que o Meteor re rendezirar a pgina

Ento ao menos que n

no tem nada a ver

que o Bootstrap est removendo o

<div>

do

O que significa dizer que o error continuar a voltar

s quisermos que os erros incessantemente voltem dos mortos para nos

lembrar de erros passados do usurio e lentamente lev los insanidade no processo

melhor n

Primeiro

s adicionarmos uma forma de remover os erros da coleo

s modificaremos a funo

throwError

til mais tarde para sabermos se um error foi de fato visto pelo usurio

,
n

s podemos condificar uma simples funo

http://pt.discovermeteor.com/pdf

para incluir a propriedade

Uma vez feito

tamb

seen . Isto ser

clearErrors

que limpa esses

152/261

1/8/2015
erros

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

seen

// Local (client-only) collection


Errors = new Meteor.Collection(null);
throwError = function(message) {
Errors.insert({message: message, seen: false})
}
clearErrors = function() {
Errors.remove({seen: true});
}

client helpers errors js

Em seguida

s limparemos os erros no roteador para ao se navegar para outra pgina n

garantirmos que esses erros desapaream para sempre

// ...
Router.before(requireLogin, {only: 'postSubmit'})
Router.before(function() { clearErrors() });

lib router js

clearErrors()

Para nossa funo

Para fazer isso devidamente

funcionar

os erros precisam ser marcados como

h um caso fronteirio que n

s precisamos resolver

lanamos um erro e ento redirecionamos o usurio para outro lugar

),

quando eles tentam enviar um link duplicado

instantaneamente

ser limpo

quando n

como n

s fazemos

o redirecionamento acontece

Isso significa que o usurio nunca tem a chance de ver o erro antes de este

que nossa propriedade

para

seen .

true

seen

ser

.
til

s precisamos assegurar que ela s

modificada

se o usurio de fato ter visto o erro

Para conseguir isso

executar seu callback

http://pt.discovermeteor.com/pdf

s usaremos o

logo depois

Meteor.defer() . Esta funo diz ao Meteor para


do que quer que esteja acontecendo

Se ajudar

voc

pode

153/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

considerar que

defer() como dizer ao navegador para esperar 1 milissegundo antes de

continuar

O que n

s estamos fazendo

ap

s o template

errors

Isto

como

ter sido renderizado

redirecionamento ocorre instataneamente

antes da callback

seen

dizer ao Meteor para modificar

para

Mas lembre se como n

true 1 milissegundo

s dissemos que o

Isto significa que o redirecionamento ocorrer

defer , a qual nunca ter uma chance de ser executada.

exatamente o que n

s queremos

se no for executada nosso error no ser marcado

visto , o que significa que no ser limpo, o que significa que aparecer na pgina para

qual nosso usurio for redirecionado assim como quer amos

Template.errors.helpers({
errors: function() {
return Errors.find();
}
});
Template.error.rendered = function() {
var error = this.data;
Meteor.defer(function() {
Errors.update(error._id, {$set: {seen: true}});
});
};

client views includes errors js

Commit93

Monitor which errors have been seen

Ver no GitHub

rendered

O callback

navegador

and clear on routing

Lanar Instncia

dispara uma vez que o nosso template ter sido renderizado no

, this

Dentro do callback

se refere instncia atual do template

this.data

nos permite acessar a informao do objeto que est atualmente sendo renderizado

caso

).

no nosso

um erro

http://pt.discovermeteor.com/pdf

154/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Whew

Isto

um monte de trabalho para algo que os usurios felizmente nunca vero

Ocallback rendered
rendered

O callback

Isto

claro

do template dispara toda vez que

inclui a primeira vez que ele aparece na tela

que o callback tamb

renderizado no navegador

mas

m disparar toda vez que o template

toda vez que qualquer de suas informa

importante lembrar

re renderizado

es mudar

Callbacks rendered normalmente dispararo ao menos duas vezes

o aplicativo ler pela primeira vez

coleo tiver sido lida

Ento voc

deveria ser disparado duas vezes

rastreamento de eventos

http://pt.discovermeteor.com/pdf

vulgo

primeiro quando

e uma segunda vez quando a informao da

deve ter cuidado ao por qualquer c

tais como um alert

digo que no

ou c

digos de anlise para

neles

155/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

CriandoumPacoteMeteorite

9.5

SIDEBAR

s constru mos um padro re utilizvel com o nosso trabalho com erros

envov

ento porque no

lo num pacote inteligente e compartilh lo com o resto da comunidade Meteor

Primeiro n

s precisamos criar alguma estrutura para o nosso pacote residir

pacote num diret

symlinks no diret

rio

s pomos o

Voc

pode ter notado que o Meteorite instala pacotes atrav

s de

packages/ .

Segundo

packages/errors . Isto cria um pacote personalizado que

rio chamado

automaticamente utilizado

s criaremos

pacote deve ser utilizado

package.js

nessa pasta

o arquivo que informa ao Meteor como o

e os s mbolos que ele exporta

Package.describe({
summary: "A pattern to display application errors to the user"
});
Package.on_use(function (api, where) {
api.use(['minimongo', 'mongo-livedata', 'templating'], 'client');
api.add_files(['errors.js', 'errors_list.html', 'errors_list.js'], 'client
');
if (api.export)
api.export('Errors');
});

packages errors package js

Vamos adicionar tr

s arquivos ao pacote

s podemos puxar esses arquivos do Microscopoe

sem muita mudana exceto por algum namespacing apropriado e uma API ligeiramente mais

limpa

http://pt.discovermeteor.com/pdf

156/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Errors = {
// Local (client-only) collection
collection: new Meteor.Collection(null),

};

throw: function(message) {
Errors.collection.insert({message: message, seen: false})
},
clearSeen: function() {
Errors.collection.remove({seen: true});
}

packages errors errors js

<template name="meteorErrors">
{{#each errors}}
{{> meteorError}}
{{/each}}
</template>
<template name="meteorError">
<div class="alert alert-error">
<button type="button" class="close" data-dismiss="alert">&times;</button
>
{{message}}
</div>
</template>

packages errors errors

list html

Template.meteorErrors.helpers({
errors: function() {
return Errors.collection.find();
}
});
Template.meteorError.rendered = function() {
var error = this.data;
Meteor.defer(function() {
Errors.collection.update(error._id, {$set: {seen: true}});
});
};

http://pt.discovermeteor.com/pdf

157/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

packages errors errors

list js

TestandoopacotecomMicroscope

Agora n

s testaremos as coisas localmente com Microscope para assegurar que o nosso

digo modificado funcione

Para ligar o pacote ao nosso projeto

s rodamos

meteor add

errors . Ento, ns precisamos deletar os arquivos existentes que se tornaram redudantes

devido ao novo pacote

$ rm client/helpers/errors.js
$ rm client/views/includes/errors.html
$ rm client/views/includes/errors.js

removing old files on the bash console

Uma outra coisa que n

s precisamos fazer

algumas pequenas atualiza

es para utilizar a API

correta

Router.before(function() { Errors.clearSeen(); });

lib router js

{{> header}}
{{> meteorErrors}}

client views application layout html

Meteor.call('post', post, function(error, id) {


if (error) {
// display the error to the user
Errors.throw(error.reason);

/ _

client views posts post

http://pt.discovermeteor.com/pdf

submit js

158/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Posts.update(currentPostId, {$set: postProperties}, function(error) {


if (error) {
// display the error to the user
Errors.throw(error.reason);

/ _

client views posts post

edit js

Commit951

Created basic errors package and linked it in

Ver no GitHub

Uma vez que essas mudanas forem feitas

pr

Lanar Instncia

pacote de volta

s devemos ter nosso comportamento original

Escrevendotestes

O primeiro passo em desenvolver um pacote

test lo num aplicativo

mas o pr

ximo

escrever um grupo de teste que testa propriamente o comportamento do pacote

si vem com Tinytest

pacote nativo de testagem

),

O Meteor em

que torna fcil rodar tais testes e manter a

paz espiritual ao compartilhar nosso pacote com outros

Vamos criar um arquivo de teste que usa Tinytest para rodar alguns testes contra a nossa base

de c

digo para errors

http://pt.discovermeteor.com/pdf

159/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Tinytest.add("Errors collection works", function(test) {


test.equal(Errors.collection.find({}).count(), 0);
Errors.throw('A new error!');
test.equal(Errors.collection.find({}).count(), 1);
Errors.collection.remove({});
});
Tinytest.addAsync("Errors template works", function(test, done) {
Errors.throw('A new error!');
test.equal(Errors.collection.find({seen: false}).count(), 1);

// render the template


OnscreenDiv(Spark.render(function() {
return Template.meteorErrors();
}));
// wait a few milliseconds
Meteor.setTimeout(function() {
test.equal(Errors.collection.find({seen: false}).count(), 0);
test.equal(Errors.collection.find({}).count(), 1);
Errors.clearSeen();
test.equal(Errors.collection.find({seen: true}).count(), 0);
done();
}, 500);
});

packages errors errors

Nesses testes n

funcionando

tests js

s estamos checando se as fun

assim como checando duas vezes que o c

est funcionando

digo

rendered

esto

no template ainda

Meteor.Errors

es bsicas de

s no cobriremos as especificidades de se escrever testes para pacotes Meteor aqui

),

a API no est finalizada e sim em alto fluxo

mas felizmente

j que

bem auto explicativo como

funciona

Para dizer ao Meteor como rodar os teste em

http://pt.discovermeteor.com/pdf

package.js , use o cdigo seguinte:

160/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Package.on_test(function(api) {
api.use('errors', 'client');
api.use(['tinytest', 'test-helpers'], 'client');
api.add_files('errors_tests.js', 'client');
});

packages errors package js

Commit952

Added tests to the package

Ver no GitHub

Ento n

s podemos rodar os testes com

Lanar Instncia

$ meteor test-packages errors

Terminal

http://pt.discovermeteor.com/pdf

161/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Passingalltests

Lanandoopacote

Agora

s queremos lanar o pacote e torn lo dispon vel para o mundo

s fazemos isso

pondo o em Atmosphere

Primeiro

s precisamos adicionar um

smart.json , para dizer ao Meteorite e Atmosphere os

detalhes importantes do pacote

"name": "errors",
"description": "A pattern to display application errors to the user",
"homepage": "https://github.com/tmeasday/meteor-errors",
"author": "Tom Coleman <tom@thesnail.org>",
"version": "0.1.0",
"git": "https://github.com/tmeasday/meteor-errors.git",
"packages": {
}

packages errors smart json

Commit953

Added a smart json

Ver no GitHub

Lanar Instncia

s pomos alguma meta informao bsica para prover informao sobre o pacote

o que ele faz

a localizao git onde n

"pacotes"

e um n

para informar as depend

Uma vez que tudo isto esteja no lugar

lanar

ncias

s tamb

mero inicial de verso

Se

m podemos utilizar o

fcil

empurrar a um servidor git remote em algum lugar

http://pt.discovermeteor.com/pdf

s vamos hosped lo

nosso pacote necessita de outros pacotes Atmosphere

segmento

incluindo

s precisaremos criar um reposit

rio git

e linkar para essa localizao no nosso

162/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

smart.json .

O processo de fazer isso para o GitHub

prtica padro para pegar o c

mrt release

comando

$ git
$ git
$ git
$ git
$ git
$ mrt
Done!

Terminal

Note

primeiro criar um novo reposit

digo do pacote de dentro do reposit

.
rio

,
rio

ento seguir a

Ento

,
n

s usamos o

para public lo

init
add -A
commit -m "Created Errors Package"
remote add origin https://github.com/tmeasday/meteor-errors.git
push origin master
release .

run from within

`)

packages errors

nome de pacotes devem ser

mesmo nome de pacote

nicos

Voc

ento voc

No futuro a Atmosphere

pode esperar que isso mude

//

- -

est seguindo palavra por palavra e usar o

precisar logar em http

senha com os quais voc

haver um conflito e no funcionar

separar os pacotes com nome de autor

Outra coisa

Se voc

atmosphere meteor com e criar um username e

entrar na linha de comando quando voc

Agora que o pacote foi lanado

chamar

mrt release . .

s podemos delet lo do nosso projeto e ento adicion lo

de volta diretamente usando Meteorite

$ rm -r packages/errors
$ mrt add errors

Terminal

run from the top level of the app

http://pt.discovermeteor.com/pdf

163/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Commit954

Removed package from development tree

Ver no GitHub

Agora n

Parab

Lanar Instncia

s devemos ver o Meteorite fazer download do nosso pacote pela primeira vez

ns

http://pt.discovermeteor.com/pdf

164/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Comentrios

10

A meta de um site social de not cias

criar uma comunidade de usurios

sem providenciar uma forma para as pessoas conversarem entre si

e ser dif cil faz

la

Ento neste cap tulo

vamos adicionar comentrios

s comearemos criando uma nova coleo para armazenar comentrios

e adicionando

alguma informao de exemplos bsica na coleo

Comments = new Meteor.Collection('comments');

collections comments js

// Fixture data
if (Posts.find().count() === 0) {
var now = new Date().getTime();
// create two users
var tomId = Meteor.users.insert({
profile: { name: 'Tom Coleman' }
});
var tom = Meteor.users.findOne(tomId);
var sachaId = Meteor.users.insert({
profile: { name: 'Sacha Greif' }
});
var sacha = Meteor.users.findOne(sachaId);
var telescopeId = Posts.insert({
title: 'Introducing Telescope',
userId: sacha._id,
author: sacha.profile.name,
url: 'http://sachagreif.com/introducing-telescope/',
submitted: now - 7 * 3600 * 1000
});
Comments.insert({
postId: telescopeId,
userId: tom._id,
author: tom.profile.name,
submitted: now - 5 * 3600 * 1000,
body: 'Interesting project Sacha, can I get involved?'
http://pt.discovermeteor.com/pdf

165/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

});
Comments.insert({
postId: telescopeId,
userId: sacha._id,
author: sacha.profile.name,
submitted: now - 3 * 3600 * 1000,
body: 'You sure can Tom!'
});
Posts.insert({
title: 'Meteor',
userId: tom._id,
author: tom.profile.name,
url: 'http://meteor.com',
submitted: now - 10 * 3600 * 1000
});

Posts.insert({
title: 'The Meteor Book',
userId: tom._id,
author: tom.profile.name,
url: 'http://themeteorbook.com',
submitted: now - 12 * 3600 * 1000
});

server fixtures js

No vamos nos esquecer de publicar e fazer assinatura nossa nova coleo

Meteor.publish('posts', function() {
return Posts.find();
});
Meteor.publish('comments', function() {
return Comments.find();
});

server publications js

http://pt.discovermeteor.com/pdf

166/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Router.configure({
layoutTemplate: 'layout',
loadingTemplate: 'loading',
waitOn: function() {
return [Meteor.subscribe('posts'), Meteor.subscribe('comments')];
}
});

lib router js

Commit101

Added comments collection

Ver no GitHub

Note que para ativar este c

o banco de dados

novo

s limpar

s criamos alguns usurios

dados e usando seus

id

voc

precisar usar

),

completamente falsos

com

,
m

s para selecion los no banco de dados mais tarde

postId , e ao usurio

com

envio e um corpo a cada comentrio

Tamb

para limpar

inserindo os no banco de

adicionamos um comentrio para cada usurio no primeiro artigo

artigo

meteor reset

no esquea de criar uma nova conta de usurio para logar de

Primeiro

Lanar Instncia

digo de exemplos

Ap

pub sub and fixtures

Ento n

ligando o comentrio ao

userId . Ns tambm adicionamos uma data de

junto com

author , um campo desnormalizado.

s melhoramos nosso roteador para esperar tanto os comentrios quanto os

artigos

Mostrandocomentrios

Est tudo certo em por comentrios no banco de dados

los na page de discusso

uma id

mas n

s tamb

m precisamos mostr

Felizmente este processo deve ser familiar a voc

agora

e voc

tem

ia dos passos envolvidos

http://pt.discovermeteor.com/pdf

167/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

<template name="postPage">
{{> postItem}}
<ul class="comments">
{{#each comments}}
{{> comment}}
{{/each}}
</ul>
</template>

/ _

client views posts post

page html

Template.postPage.helpers({
comments: function() {
return Comments.find({postId: this._id});
}
});

/ _

client views posts post

s pomos o bloco

page js

{{#each comments}}

artigo dentro do ajudante

linear

s do atributo

this um

postId .

s aprendemos sobre ajudantes e handlebars

.
N

ento

comments . Para encontrar comentrios relevantes, ns checamos

aqueles que esto ligados ao post atrav

Dado que n

dentro do template do artigo

s criaremos um novo diret

rio

comments

renderizar um comentrio

dentro de

views

bem

para armazenar toda

nossa informao de comentrio

<template name="comment">
<li>
<h4>
<span class="author">{{author}}</span>
<span class="date">on {{submittedText}}</span>
</h4>
<p>{{body}}</p>
</li>
</template>

client views comments comment html

http://pt.discovermeteor.com/pdf

168/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Vamos configurar um simples ajudante de template para formatar nossa informao

submitted

para um formato leg vel por humanos

pessoas que conseguem entender c

?)

a menos que voc

seja uma daquelas

digos de UNIX timestamps e cores hexadecimais

fluentemente

Template.comment.helpers({
submittedText: function() {
return new Date(this.submitted).toString();
}
});

client views comments comment js

Ento

s mostraremos o n

mero de comentrios de cada artigo

<template name="postItem">
<div class="post">
<div class="post-content">
<h3><a href="{{url}}">{{title}}</a><span>{{domain}}</span></h3>
<p>
submitted by {{author}},
<a href="{{pathFor 'postPage'}}">{{commentsCount}} comments</a>
{{#if ownPost}}<a href="{{pathFor 'postEdit'}}">Edit</a>{{/if}}
</p>
</div>
<a href="{{pathFor 'postPage'}}" class="discuss btn">Discuss</a>
</div>
</template>

/ _

client views posts post

item html

E adicionaremos o ajudante

http://pt.discovermeteor.com/pdf

commentsCount

ao nosso administrador

postItem :

169/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Template.postItem.helpers({
ownPost: function() {
return this.userId == Meteor.userId();
},
domain: function() {
var a = document.createElement('a');
a.href = this.url;
return a.hostname;
},
commentsCount: function() {
return Comments.find({postId: this._id}).count();
}
});

/ _

client views posts post

item js

Commit102
Display comments on

Ver no GitHub

`.

postPage

Lanar Instncia

s devemos ser capazes de mostrar nossos comentrios de exemplo e ver algo assim

http://pt.discovermeteor.com/pdf

170/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Displayingcomments

EnviandoComentrios

Vamos adicionar uma forma dos nossos usurios criarem comentrios

O processo que

seguiremos ser bem similar ao como n

s criamos usurios para criar novos artigos

s comearemos por adicionar uma caixa de envio no fim de cada artigo

<template name="postPage">
{{> postItem}}
<ul class="comments">
{{#each comments}}
{{> comment}}
{{/each}}
</ul>
{{#if currentUser}}
{{> commentSubmit}}
{{else}}
<p>Please log in to leave a comment.</p>
{{/if}}
</template>

/ _

client views posts post

page html

E ento criar um template de formulrio de comentrio

http://pt.discovermeteor.com/pdf

171/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

<template name="commentSubmit">
<form name="comment" class="comment-form">
<div class="control-group">
<div class="controls">
<label for="body">Comment on this post</label>
<textarea name="body"></textarea>
</div>
</div>
<div class="control-group">
<div class="controls">
<button type="submit" class="btn">Add Comment</button>
</div>
</div>
</form>
</template>

client views comments comment

submit html

Thecommentsubmitform

Para enviar nossos comentrios

commentSubmit

s chamamos um M

todo

comment

que opera de uma forma similar ao administrador

http://pt.discovermeteor.com/pdf

no administrador

postSubmit :

172/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Template.commentSubmit.events({
'submit form': function(e, template) {
e.preventDefault();
var $body = $(e.target).find('[name=body]');
var comment = {
body: $body.val(),
postId: template.data._id
};

}
});

Meteor.call('comment', comment, function(error, commentId) {


if (error){
throwError(error.reason);
} else {
$body.val('');
}
});

client views comments comment

submit js

Assim como n

configuraremos um M

leg timo

s previamente configuramos um M

todo Meteor

comment

todo

post

do lado do servidor

para criar nossos comentrios

,
n

cheque que tudo

e finalmente insira o novo comentrio na coleo de comentrios

http://pt.discovermeteor.com/pdf

173/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Comments = new Meteor.Collection('comments');


Meteor.methods({
comment: function(commentAttributes) {
var user = Meteor.user();
var post = Posts.findOne(commentAttributes.postId);
// ensure the user is logged in
if (!user)
throw new Meteor.Error(401, "You need to login to make comments");
if (!commentAttributes.body)
throw new Meteor.Error(422, 'Please write some content');
if (!post)
throw new Meteor.Error(422, 'You must comment on a post');
comment = _.extend(_.pick(commentAttributes, 'postId', 'body'), {
userId: user._id,
author: user.username,
submitted: new Date().getTime()
});
}
});

return Comments.insert(comment);

collections comments js

Commit103

Created a form to submit comments

Ver no GitHub

Isto no est fazendo nada requintado

comentrio tem um corpo

Lanar Instncia

apenas checando se o usurio est logado

que o

e que esteja ligado a um artigo

ControlandoaAssinaturadosComentrios

Como as coisas esto

s estamos publicando todos comentrios de todos os artigos para

todos os clientes conectados

http://pt.discovermeteor.com/pdf

Isso

um desperd cio

J que

s estamos apenas utilizando

174/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

um pequeno subconjunto da informao a qualquer momento que for

Vamos melhorar nossa

publicao e assinatura para controlar exatamente quais comentrios so publicados

Se n

s pensarmos sobre isso

publicao dos nossos

nico momento que n

s precisamos fazer a assinatura para a

comments quando o usurio acessa a pgina individual do artigo, e

s precisamos apenas ler um subconjunto dos comentrios relacionados a este artigo em

particular

O primeiro passo ser mudar a forma como n

agora

s fazemos a assinatura para os comentrios

s temos feito a assinatura no n vel do roteador

nossa informao quando o roteador

o que significa que n

s lemos toda

inicializado

Mas n

s agora queremos que a nossa assinatura dependa de um parmetro path

parmetro pode obviamente mudar a qualquer momento

nosso c

At

Ento n

e esse

s precisaremos mover

digo de assinatura do n vel do roteador para o n vel da rota

Isto tem outra conseq

ncia

ao inv

s de ler nossa informao quando n

nosso aplicativo

que voc

s agora a leremos toda vez que n

s inicializamos

s alcanamos nossa rota

Isto significa

agora ter momentos de loading enquanto navega dentro do aplicativo

vagamente negativo a no ser que voc

um ponto

queira ler de vez o seu conjunto de informao todo

para sempre

Assim que a nossa nova funo

http://pt.discovermeteor.com/pdf

waitOn

ao n vel da rota se parece

175/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Router.map(function() {

//...
this.route('postPage', {
path: '/posts/:_id',
waitOn: function() {
return Meteor.subscribe('comments', this.params._id);
},
data: function() { return Posts.findOne(this.params._id); }
});

//...
});

lib router js

Voc

perceber que n

assinatura

s estamos passando

this.params._id

como um argumento

Ento usamos essa nova informao para garantir que n

s restrinjamos nosso

conjunto de informao aos comentrio pertencentes ao artigo atual

Meteor.publish('posts', function() {
return Posts.find();
});
Meteor.publish('comments', function(postId) {
return Comments.find({postId: postId});
});

server publications js

Commit104

Made a simple publication subscription for comments

Ver no GitHub

H apenas um problema

http://pt.discovermeteor.com/pdf

quando n

Lanar Instncia

s retornamos pgina inicial

ela diz que todos nossos

176/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

artigos tem

comentrios

Ourcommentsaregone!

ContandoComentrios

A razo para isto ficar logo clara

do artigo lido

ajudante

ento quando n

commentsCount

:
n

s apenas temos no mximo um dos nossos comentrios

s chamamos

no administrador

Comments.find({postId: this._id})

no

post_item , Meteor no consegue encontrar a

informao necessria do lado do cliente para nos prover um resultado

A melhor maneira para lidar com isto

voc

desnormalizar o n

no est certo do que isso significa no se preocupe

!).

isso

Como veremos

mero de comentrios do artigo

a pr

se

xima barra lateral cobrir

h uma pequena adio de complexidade no nosso c

de performance que n

digo

o benef cio

s ganhamos de no ter que publicar todos comentrios para mostrar a

lista de artigos vale a pena

s conseguiremos isso ao adicionar uma propriedade

estrutura do

reset

post.

los

http://pt.discovermeteor.com/pdf

informao de

Para comear

para rel

commentsCount

s atualizamos nossos exemplos de artigo

no esquea de recriar sua conta de usurio depois

):

meteor

177/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

var telescopeId = Posts.insert({


title: 'Introducing Telescope',
..
commentsCount: 2
});
Posts.insert({
title: 'Meteor',
...
commentsCount: 0
});
Posts.insert({
title: 'The Meteor Book',
...
commentsCount: 0
});

server fixtures js

Ento

s garantimos que todos novos artigos comecem com

comentrio

// pick out the whitelisted keys


var post = _.extend(_.pick(postAttributes, 'url', 'title', 'message'), {
userId: user._id,
author: user.username,
submitted: new Date().getTime(),
commentsCount: 0
});
var postId = Posts.insert(post);

collections posts js

E ento n

s atualizamos o

commentsCount

comentrio usando o operador Mongo

http://pt.discovermeteor.com/pdf

relevante quando n

$inc

s fazemos um novo

o qual incrementa o campo num

rico por um

):

178/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

// update the post with the number of comments


Posts.update(comment.postId, {$inc: {commentsCount: 1}});
return Comments.insert(comment);

collections comments js

Finalmente

s podemos apenas remover o ajudante

commentsCount

do

client/views/posts/post_item.js , j que o campo est agora diretamente disponvel no

nosso artigo

Commit105

Denormalized the number of comments into the post

Ver no GitHub

Lanar Instncia

Agora que nossos usurios podem conversar entre si

dos novos comentrios

notifica

E sabe mais

o pr

seria uma pena se eles no soubessem

ximo cap tulo mostrar a voc

como implementar

es para previnir exatamente isto

http://pt.discovermeteor.com/pdf

179/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Desnormalizao

10.5

SIDEBAR

Desnormalizar a informao significa no armazen la de forma

palavras

desnormalizao significa ter m

ltiplas c

normal

Em outras

pias do mesmo pedao de informao por

No

ltimo cap tulo

s desnormalizamos a contagem do n

mero de comentrios no objeto

post para evitar ter de ler todos os comentrios o tempo todo

informao isto

redundante

j que n

Num sentido de modelagem da

s pod amos apenas contar o conjunto correto de

comentrio a qualquer momento para descobrir o valor

).

deixando de lado considera

es

quanto performance

Desnormalizao geralmente significa trabalho extra para o desenvolvedor

exemplo

cada vez que n

s adicionamos ou removemos um comentrio n

No nosso

s tamb

precisamos nos lembrar de atualizar o artigo relevante para assegurar que o campo

commentsCount

continue correto

Isto

exatamente o porqu

de bancos de dados relacionais

como MySQL franzirem as sobrancelhas para isto tipo de procedimento

Entretanto

o procedimento normal tamb

m tem suas desvantagens

commentsCount , ns precisaramos mandar

apenas para sermos capazes de cont los

sem uma propriedade

todos os comentrios pela fiao todas as vezes

o que era o que estvamos fazendo no in cio

Desnormalizar nos permite evitar isso completamente

UmaPublicaoEspecial

Seria poss vel criar uma publicao especial que enviaria apenas a contagem de

comentrios que n

artigos que n

Mas

s estamos interessados

s atualmente vemos

atrav

vulgo a contagem de comentrios de

).

s de consultas agregadas no servidor

vlido considerar se a complexidade de tal c

digo de publicao no pesa mais

que as dificuldades criadas por desnormalizar

http://pt.discovermeteor.com/pdf

180/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Claro

tais considera

digo onde a integridade da informao

na informao

es devem ser espec ficas ao aplicativo

se voc

de suma importncia

est escrevendo um

ento evitar inconsist

bem mais importante e de uma ordem de prioridade maior para voc

ncias

do que

ganhos de performance

EmbutindoDocumentosouCriandoColeesMltiplas

Se voc

experiente em Mongo

voc

pode ter se surpreendido ao ver que n

segunda coleo apenas para os comentrios

por que no apenas imbut

s criamos uma

los numa lista

dentro do documento artigo

A questo

que vrias das ferramentas que o Meteor d funcionam bem melhor quando se

opera ao n vel da coleo

1.

O ajudante

de

Por exemplo

{{#each}} bem eficiente quando interando sobre um cursor

o resultado

collection.find() . O mesmo verdadeiro quando ele intera sobre um array de

objetos dentro de um documento maior

2. allow

deny

operam no n vel do documento

qualquer modifica

e ento torna mais fcil assegurar que

es em comentrios individuais esto corretas de uma forma que

seria mais complexa se n

3.

s operassemos no n vel do artigo

DDP opera ao n vel de atributos de n vel superior do documento

comments
no artigo

fosse uma propriedade do

isto significa se

post , cada vez que um comentrio fosse criado

o servidor enviaria a lista de comentrios inteira atualizada do artigo para

cada cliente conectado

4.

Publica

es e assinaturas so bem mais fceis de controlar no n vel dos documentos

Por exemplo

se n

s quisermos paginar os comentrios do artigo seria dif cil a no ser

que os comentrios estivessem em sua pr

pria coleo

Mongo sugere documentos embutidos para reduzir o n

pegar documentos

Entretanto

arquitetura do Meteor

cliente

isto no

http://pt.discovermeteor.com/pdf

tanto a questo quando se leva em considerao a

a maior parte do tempo n

onde o acesso ao banco de dados

mero de consultas despendiosas para

s estamos consultando comentrios no

essencialmente livre

181/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

AsDesvantagensdaDesnormalizao
H um bom argumento a ser feito sobre porque no devemos desnormalizar nossa

informao

Para uma boa olhada sobre o caso contra a desnormalizao

recomendamos Why You Should Never Use MongoDB por Sarah Mei

http://pt.discovermeteor.com/pdf

182/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Notificaes

11

Agora que os usurios possam comentar nos artigos uns dos outros

seria bom permit

los

saber que uma conversa comeou

Para tanto

s notificaremos o dono do artigo de que houve um comentrio em seu artigo

providenciaremos um link para eles verem esse comentrio

Este

o tipo de utilidade onde o Meteor realmente brilha

padro

s mostraremos essas notifica

por o Meteor ser em tempo real por

es instantaneamente

s no precisamos esperar o

usurio atualizar a pgina ou checar manualmente

novas notifica

es sem precisar escrever nenhum c

s podemos simplesmente pipocar

digo especial

Criandonotificaes

s criaremos uma notificao quando algu

notifica

m comenta nos seus artigos

es podero ser estendidas para cobrir muitos outros cenrios

No futuro

mas por hora isso

seria o suficiente para manter os usurios informados do que est acontecendo

Vamos criar nossa coleo

Notifications , assim como uma funo

createCommentNotification

que inserir uma notificao correspondente a cada novo

comentrio em um de seus artigos

http://pt.discovermeteor.com/pdf

183/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Notifications = new Meteor.Collection('notifications');


Notifications.allow({
update: ownsDocument
});
createCommentNotification = function(comment) {
var post = Posts.findOne(comment.postId);
if (comment.userId !== post.userId) {
Notifications.insert({
userId: post.userId,
postId: post._id,
commentId: comment._id,
commenterName: comment.author,
read: false
});
}
};

collections notifications js

Assim como artigos e comentrios

pelo cliente quanto pelo servidor

que o usurio j as viu

que n

s tamb

s restrinjamos as permiss

Notifications

ser compartilhada tanto

J que n

s precisamos atualizar as notifica

m disponibilizamos atualiza

,
es

es uma vez

garantindo como sempre

es de atualizao pr

pria informao do usurio

s tamb

m criamos uma simples funo que olha para o artigo que o usurio est

comentando

descobre quem deve ser notificado a partir da

esta coleo

s j estamos criando comentrios com um M

todo do lado do servidor

apenas melhorar este M

_id

todo para chamar a nossa funo

Comments.insert(comment);

por

do rec

e insere uma nova notificao

ento n

s trocaremos

return

comment._id = Comments.insert(comment)

m criado comentrio em uma varivel

s podemos

para salvar a

ento chamamos nossa funo

createCommentNotification :

http://pt.discovermeteor.com/pdf

184/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Comments = new Meteor.Collection('comments');


Meteor.methods({
comment: function(commentAttributes) {

// [...]
// create the comment, save the id
comment._id = Comments.insert(comment);
// now create a notification, informing the user that there's been a com
ment
createCommentNotification(comment);
return comment._id;

}
});

collections comments js

Vamos tamb

m publicar as notifica

es

e fazer assinatura no cliente

// [...]
Meteor.publish('notifications', function() {
return Notifications.find();
});

server publications js

Router.configure({
layoutTemplate: 'layout',
loadingTemplate: 'loading',
waitOn: function() {
return [Meteor.subscribe('posts'), Meteor.subscribe('notifications')]
}
});

lib router js

http://pt.discovermeteor.com/pdf

185/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Commit111

Added basic notifications collection

Ver no GitHub

Lanar Instncia

MostrandoNotificaes

Agora n

s podemos ir em frente e adicionar uma lista de notifica

es ao cabealho

<template name="header">
<header class="navbar">
<div class="navbar-inner">
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-col
lapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<a class="brand" href="{{pathFor 'postsList'}}">Microscope</a>
<div class="nav-collapse collapse">
<ul class="nav">
{{#if currentUser}}
<li>
<a href="{{pathFor 'postSubmit'}}">Submit Post</a>
</li>
<li class="dropdown">
{{> notifications}}
</li>
{{/if}}
</ul>
<ul class="nav pull-right">
<li>{{loginButtons}}</li>
</ul>
</div>
</div>
</header>
</template>

client views includes header html

E criar os templates

notifications

http://pt.discovermeteor.com/pdf

notification

eles compartilharo um mesmo

186/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

arquivo

notifications.html :

<template name="notifications">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
Notifications
{{#if notificationCount}}
<span class="badge badge-inverse">{{notificationCount}}</span>
{{/if}}
<b class="caret"></b>
</a>
<ul class="notification dropdown-menu">
{{#if notificationCount}}
{{#each notifications}}
{{> notification}}
{{/each}}
{{else}}
<li><span>No Notifications</span></li>
{{/if}}
</ul>
</template>
<template name="notification">
<li>
<a href="{{notificationPostPath}}">
<strong>{{commenterName}}</strong> commented on your post
</a>
</li>
</template>

client views notifications notifications html

s podemos ver que o plano

comentado

que cada notificao contenha um link para o artigo que foi

e o nome do usurio que comentou

Em seguida

s precisamos ter certeza que n

nosso administrador

e atualizamos as notifica

s selecionamos a lista certa de notifica

es como

lidas

es no

quando o usurio clica no

link para onde elas apontam

http://pt.discovermeteor.com/pdf

187/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Template.notifications.helpers({
notifications: function() {
return Notifications.find({userId: Meteor.userId(), read: false});
},
notificationCount: function(){
return Notifications.find({userId: Meteor.userId(), read: false}).count(
);
}
});
Template.notification.helpers({
notificationPostPath: function() {
return Router.routes.postPage.path({_id: this.postId});
}
})
Template.notification.events({
'click a': function() {
Notifications.update(this._id, {$set: {read: true}});
}
})

client views notifications notifications js

Commit112

Display notifications in the header

Ver no GitHub

Voc

pode pensar que notifica

estrutura deles

bem similar

lado do cliente sincronizada

que n

Lanar Instncia

es no so to diferentes de erros

,
e

verdade que a

H uma grande diferena por

Isto significa que nossas notifica

s usemos a mesma conta de usurio

s criamos uma coleo do

es so persistentes e

desde

elas existiro ao longo de atualiza

es do

navegador e diferentes dispositivos

Tente

abra um segundo navegador

comente num artigo que voc

).

Chrome

Voc

),

digamos o Firefox

crie uma nova conta de usurio

criou com sua conta principal

deve ver algo assim

http://pt.discovermeteor.com/pdf

a qual voc

deixou aberta no

188/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Displayingnotifications.

Controlandoacessosnotificaes

As notifica

es esto funcionando devidamente

notifica

Se voc

es so p

Entretanto h um pequeno problema

nossas

blicas

ainda tiver seu segundo navegador aberto

tente rodar o c

digo seguinte no console

do navegador

Notifications.find().count();

Browser console

Este novo usurio

aquele que comentou

que eles podem ver na coleo

no deve ter nenhuma notificao

Notifications

As notifica

es

na verdade pertencem ao nosso usurio

original

Pondo de lado quest

http://pt.discovermeteor.com/pdf

es de privacidade em potencial

s simplesmente no podemos ter

189/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

todas notifica

es de cada usurio sendo lidas no navegador dos outros usurios

grande o suficiente

isso poderia sobrecarregar a mem

a causar s

ria dispon vel do navegador e comear

rios problemas de performance

Num site

s solucionamos essa questo com publica

es

s podemos usar nossas publica

es para

especificar precisamente que parte da nossa coleo n

navegador

s queremos compartilhar com cada

.
,

Para conseguir isso

na nossa publicao

s precisamos retornar um cursor diferente de

Notifications.find()

.
N

s queremos retornar um cursor que corresponda s notifica

es do

usurio logado

Fazer isso

em

bem linear

j que uma funo

publish

tem dispon vel a

_id

do usurio logado

this.userId :

Meteor.publish('notifications', function() {
return Notifications.find({userId: this.userId});
});

server publications js

Commit113

Only sync notifications that are relevant to the user

Ver no GitHub

Agora se n

cole

Lanar Instncia

s checarmos nas nossas duas janelas de navegador

es de notifica

s devemos ver duas

es diferentes

Notifications.find().count();

http://pt.discovermeteor.com/pdf

190/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Browser console

user

Notifications.find().count();

Browser console

Na verdade

aplicativo

user

a lista de Notifica

Isto

usurio muda

es deve at

mudar quando o usurio logar e deslogar do

porque publica

es automaticamente re publicam toda vez que a conta de

Nosso aplicativo est se tornando cada vez mais e mais funcional

se cadastrarem e comearem a postar links n

homepage sem fim

http://pt.discovermeteor.com/pdf

e assim que mais usurios

s correremos o risco de terminar com uma

s checaremos isso no pr

ximo cap tulo ao implementar paginao

191/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

ReatividadeAvanada

raro voc

mesmo precisar escrever c

til entend

gostaram

digo para rastrear depend

ncias

mas

certamente

s gostar amos de rastrear quantos amigos de Facebook do usurio logado

de cada artigo no Microscope

como autenticar o usurio com Facebook

informao relevante

lo para traar como funciona o caminho do fluxo de resoluo

Imagine que n

11.5

SIDEBAR

Vamos supor que n

fazer as chamadas API apropriadas

.
N

s j resolvemos os detalhes de

e anlise da

s agora temos uma funo ass ncrona do lado do cliente que retorna

, getFacebookLikeCount(user, url, callback) .

o n

mero de likes

A coisa importante a se lembrar sobre tal funo

tempo real

Ela far um pedido HTTP ao Facebook

dispon vel aplicao num callback ass ncrono

contagem mudar no Facebook

que ela

bastante no reativa e no em

trar alguma informao

e a far

mas a funo no re rodar sozinha quando a

e nossa UI no mudar quando a informao subjacente

mudar

Para consertar isso

s podemos comear por usar

setInterval

para chamar nossa funo

a cada alguns segundos

currentLikeCount = 0;
Meteor.setInterval(function() {
var postId;
if (Meteor.user() && postId = Session.get('currentPostId')) {
getFacebookLikeCount(Meteor.user(), Posts.find(postId),
function(err, count) {
if (!err)
currentLikeCount = count;
});
}
}, 5 * 1000);

A qualquer momento que n

s checarmos a varivel

o n

mero correto com uma margem de erro de

currentLikeCount , ns podemos esperar

segundos

s podemos agora usar esta

varivel num ajudante assim

http://pt.discovermeteor.com/pdf

192/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Template.postItem.likeCount = function() {
return currentLikeCount;
}

Entretanto

mudar

nada ainda diz ao nosso template para re desenhar quando

currentLikeCount

Apesar da varivel ser agora pseudo em tempo real j que ela muda sozinha

ela no

reativa ento ela ainda no consegue se comunicar devidamente com o resto do ecosistema

do Meteor

RastreandoReatividade:Computaes

A reatividade do Meteor

mediada por depend

ncias

estruturas de informao que rastreiam

um conjunto de computa

es

Como n

do c

s vimos anteriormente na barra lateral reatividade

digo que usa informao reativa

criada implicitamente pelo template

No nosso caso

uma computao

um segmento

h uma computao que est sendo

postItem . Cada ajudante no administrador desse

template est trabalhando dentro da computao

Voc

pode pensar na computao como o segmento de c

informao reativa

via

Quando a informao muda

digo que

se importa

quanto

esta ser a computao que ser informada

invalidate() , e a computao que decide quando algo precisa ser feito.

TransformandoumaVarivelemumaFunoReativa

Para tornar nossa varivel

currentLikeCount

precisamos rastrear todas as computa

es que a utilizam em uma depend

mud la de uma varivel em uma funo

http://pt.discovermeteor.com/pdf

em uma fonte de informao reativa

):

ncia

,
n

Isto requer

que retornar um valor

193/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

var _currentLikeCount = 0;
var _currentLikeCountListeners = new Deps.Dependency();
currentLikeCount = function() {
_currentLikeCountListeners.depend();
return _currentLikeCount;
}
Meteor.setInterval(function() {
var postId;
if (Meteor.user() && postId = Session.get('currentPostId')) {
getFacebookLikeCount(Meteor.user(), Posts.find(postId),
function(err, count) {
if (!err && count !== _currentLikeCount) {
_currentLikeCount = count;
_currentLikeCountListeners.changed();
}
});
}
}, 5 * 1000);

O que n

s fizemos foi configurar uma depend

rastreia todas as computa

muda

a qual invalida todas as computa

Essas computa

ncia

es dentro das quais

_currentLikeCount

valor de

_currentLikeCountListerners , a qual

currentLinkCount()

s chamamos a funo

es rastreadas

foi utilizada

changed()

Quando o

nesta depend

ncia

.
.

es podem ento ir em frente e lidarem com a mudana caso a caso

caso da computao do template

Neste

parece que o template re desenha a si mesmo

ComputaodeTemplateeControlandooRedesenhar

A razo de porque cada template tem sua pr

pria computao

para controlar a quantidade

de redesenhar que ocorre na tela

Quando n

s chamamos um template de dentro de outro

segunda computao dentro da primeira

interior muda

este template interior

intacto

Desta forma

s estamos estabelecendo uma

Ento quando a informao reativa do template

redesenhado por

m o template exterior continua

computa

es so utilizadas para controlar o escopo das mundanas

reativas

http://pt.discovermeteor.com/pdf

194/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

O Meteor tamb

m nos d um pouco de ajuda extra para melhorar os mecanismos bsicos de

aninhar templates

Primeiro

{{#constant}}

o ajudante em bloco

qualquer informao que

mata a reatividade dentro de si

colhida pelos ajudantes dentro do bloco

E mesmo que o template exterior seja redesenhado

Isto faz das regi

Ento

apenas usada uma vez

o HTML da rea constante

lado j que seria renderizado de mesma exata forma

deixado de

es constantes uma

grande forma de adminsitrar widgets de terceiros que no esto esperando que o Meteor re

desenhe o DOM sob eles

O segundo utilitrio que pode nos ajudar a controlar a reativiadde

{{#isolate}} , o qual configura uma

palavras

o ajudante em bloco

nova computao dentro de um template

Em outras

tem o mesmo efeito de mover um segmento do template para dentro de um sub

template em termos de reatividade e redesenho

Ento se uma das fontes de informao reativa dentro do bloco isolate mudar

ser re desenhada

mas o remanecescente do template superior no

re desenhar por

a rea isolada ser redesenhada tamb

a rea isolada

Se o template superior

.
m

ComparandoDepsaAngular

Angular

uma biblioteca de renderizao reativa do lado do cliente apenas

pelo bom pessoal do Google

Meteor e do Angular

interessante comparar o modo de rastrear depend

j que os modos so bem diferentes

s vimos que o modelo do Meteor usa blocos de c

computa

ncias quando eles precisam chamar

geralmente quando informao muda

apesar que computa

reativas

fun

es

Essas

que tratam de

invalidate() . Note que apesar que isso

.
es

es usualmente apenas re rodam quando invalidadas

pode configur las para se comportar de qualquer forma que voc

http://pt.discovermeteor.com/pdf

es

a fonte de informao poderia potencialmente decidir

desencadear uma invalidao por outras raz

Ento a fonte de informao explicitamente informa todas as

Adicionalmente

es

ncias do

digos chamados computa

invalid las quando necessrio

voc

es so rastreadas por fontes de informa

suas depend

desenvolvida

quiser

195/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Em Angular

a reatividade

mediada pelo objeto

scope . Um escopo pode ser pensado como

um objeto JavaScript comum com alguns m

Quando voc

todos especiais

.
,

quer reativamente depender em um valor em um escopo

scope.$watch , providenciando a expresso que voc est interessado

escopo voc

Ento voc

se importa

voc

chama

vulgo quais partes do

e uma funo ouvinte que rodar cada vez que a expresso mudar

explicitamente afirma exatamente o que voc

quer que seja feito toda vez que o

valor da expresso mudar

Voltando ao nosso exemplo do Facebook

,
n

s escrever amos

$rootScope.$watch('currentLikeCount', function(likeCount) {
console.log('Current like count is ' + likeCount);
});

Claro

assim como voc

$watch

raramente configura computa

explicitamente com freq

{{expressions}}

ncia em Angular pois diretivas

no chama

ng-model

, scope.$apply()

Quando tal valor reativo mudar

cada observador do escopo

deve ento ser chamado

Isto re avalia

mas apenas chama a funo ouvinte dos observadores dos quais

o valor da expresso tenha mudado

scope.$apply() similar a dependency.changed() , exceto por agir no nvel do

escopo

voc

automaticamente configuram watches que ento cuidam de re

renderizarem quando h mudana

Ento

es em Meteor

ao inv

re avaliados

s de lhe dar o controle quanto a dizer precisamente quais ouvintes devem ser

Tendo dito isto

esta leve falta de controle d a Angular a habilidade de ser bem

inteligente e eficiente na forma como ele determina precisamente quais ouvintes precisam ser

re avaliados

.
,

Com Angular

nosso c

http://pt.discovermeteor.com/pdf

digo da funo

getFacebookLikeCount()

se pareceria com algo assim

196/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Meteor.setInterval(function() {
getFacebookLikeCount(Meteor.user(), Posts.find(postId),
function(err, count) {
if (!err) {
$rootScope.currentLikeCount = count;
$rootScope.$apply();
}
});
}, 5 * 1000);

Admitidamente

o Meteor toma conta da maior parte do trabalho pesado para n

colher os benef cios da reatividade sem muito trabalho da nossa parte

aprender sobre esses padr

es se mostrar

s e nos deixa

Mas felizmente

til se alguma vez precisarmos levar as coisas mais

adiante

http://pt.discovermeteor.com/pdf

197/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Paginao

12

O Microscope est com muito bom aspeto

e podemos esperar uma recepo calorosa quando

este for lanado para o mundo

Assim provavelmente

boa ideia pensar um pouco sobre as implica

es de performance do

mero de artigos novos que vo ser criados no site quando este for lanado

Anteriormente falmos de como uma coleo no lado do cliente deve conter um sub conjunto

dos dados no servidor

e at

conseguimos atingir isto para as nossas cole

es de notifica

es

e comentrios

No entanto

atualmente ainda estamos a publicar todos os artigos de uma vez

utilizadores ligados

problemtico

Eventualmente

Para resolver isto

se milhares de links forem submetidos

para todos os

isto ser

precisamos de paginar os artigos

AdicionandoMaisArtigos

Primeiro

nos nossos dados de teste

faa realmente sentido

http://pt.discovermeteor.com/pdf

vamos carregar artigos suficientes para que a paginao

198/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

// Fixture data
if (Posts.find().count() === 0) {
//...
Posts.insert({
title: 'The Meteor Book',
userId: tom._id,
author: tom.profile.name,
url: 'http://themeteorbook.com',
submitted: now - 12 * 3600 * 1000,
commentsCount: 0
});

for (var i = 0; i < 10; i++) {


Posts.insert({
title: 'Test post #' + i,
author: sacha.profile.name,
userId: sacha._id,
url: 'http://google.com/?q=test-' + i,
submitted: now - i * 3600 * 1000,
commentsCount: 0
});
}

server fixtures js

Depois de executar

meteor reset , voc deve obter algo como:

http://pt.discovermeteor.com/pdf

199/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Mostrandodadosdeteste.

Commit121

Foram adicionados artigos suficientes para que a pagina

Ver no GitHub

Lanar Instncia

PaginaoInfinita

Vamos implementar uma paginao estilo

que vamos primeiro mostrar

fundo

, 10

por exemplo

Clicar neste link vai adicionar mais

infinito

10

O que queremos dizer por este termo

artigos no ecr

artigos lista

com um link

carregar mais

e por ai adiante ad infinitum

significa que podemos controlar todo o sistema de paginao com um

representa o n

no

Isto

nico parmetro que

mero de artigos a mostrar no ecr

Agora vamos precisar de uma forma de comunicar este parmetro ao servidor para que ele

fique a saber quantos artigos enviar para o cliente

publicao

posts

no roteador

Acontece que j estamos a subscrever

portanto vamos tirar vantagem disto e deixar ser tamb

m o

roteador lidar com a paginao

http://pt.discovermeteor.com/pdf

200/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

A forma mais fcil de configurar isto

parte do caminho

simplesmente fazendo o parmetro limite de artigos

dando nos URLs na forma

http://localhost:3000/25 . Um bons

adicional de usar o URL comparativamente a outros m

mostrar

ver

25

25

todos

que se estamos atualmente a

artigos e por acaso fazemos refresh ao navegador por engano

vamos continuar a

artigos quando a pgina voltar a carregar

Para fazer isto corretamente

artigos

vamos precisar de alterar a forma como subscrevemos aos

Tal como previamente fizemos no capitulo Comentrios

nosso c

vamos precisar de mover o

digo da subscrio do n vel do roteador para o n vel da rota

Isto tudo pode ser muito para interiorizar de uma vez

Primeiro

vamos parar de subscrever publicao

Basta remover

mas vai ficar mais claro vendo o c

posts

no bloco

digo

Router.configure() .

Meteor.subscribe('posts'), , deixando apenas a subscrio s

notifications :

Router.configure({
layoutTemplate: 'layout',
loadingTemplate: 'loading',
waitOn: function() {
return [Meteor.subscribe('notifications')]
}
});

lib router js

Depois vamos adicionar um parmetro

postsLimit

depois do nome do parmetro significa que

combinar com

ao caminho da rota

opcional

Ou seja

Adicionar um

a nossa rota no s

vai

http://localhost:3000/50 , mas tambm com o antigo

http://localhost:3000 .

http://pt.discovermeteor.com/pdf

201/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Router.map(function() {
//...
this.route('postsList', {
path: '/:postsLimit?'
});
});

lib router js

importante notar que um caminho na forma

caminhos poss veis

/:parameter?

vai combinar com todos os

Dado que cada rota vai ser analisada sucessivamente para ver se combina

com o caminho atual

temos de garantir que organizamos as nossas rotas por ordem de

especificidade decrescente

Noutras palavras

vir primeiro

rotas que apontem para rotas mais espec ficas como

e a nossa rota

postsList

/posts/:_id

devem

deve ser movida para o fundo do ficheiro dado que

basicamente combina com tudo

Est agora na altura de lidar com o problema dif cil de subscrever e encontrar os dados

corretos

Precisamos de lidar com o caso em que o parmetro

caso em que lhe damos um valor por defeito

brincar com a paginao

Vamos usar

postsLimit

no est presente

para podermos ter espao para

Router.map(function() {
//..
this.route('postsList', {
path: '/:postsLimit?',
waitOn: function() {
var postsLimit = parseInt(this.params.postsLimit) || 5;
return Meteor.subscribe('posts', {sort: {submitted: -1}, limit: postsL
imit});
}
});
});

lib router js

http://pt.discovermeteor.com/pdf

202/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Vai notar que estamos agora a passar um objecto JavaScript

com o nome da nossa publicao

options

para o c

posts

digo de servidor

).

artigos

({

limit

postsLimit

})

em conjunto

Este objecto vai servir como o parmetro

Posts.find() . Vamos passar para o nosso cdigo de

servidor para implementar isto

Meteor.publish('posts', function(options) {
return Posts.find({}, options);
});
Meteor.publish('comments', function(postId) {
return Comments.find({postId: postId});
});
Meteor.publish('notifications', function() {
return Notifications.find({userId: this.userId});
});

server publications js

http://pt.discovermeteor.com/pdf

203/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

PassandoParmetros

O nosso c

digo das publica

es est com efeito a dizer ao servidor que este pode

confiar em qualquer objecto JavaScript enviado pelo cliente

postsLimit}

options

para servir como as

da operao de

, {limit:

no nosso caso

find() . Isto torna

poss vel que utilizadores possam submeter qualquer opo que queiram atrav

s da

consola do navegador

No nosso caso

fazer

isto

relativamente segura

dado que tudo o que o utilizador pode

re ordenar artigos de forma diferente

).

ou mudar o limite

que

o que

quer amos fazer em primeiro lugar

No entanto esta abordagem no deve ser usada quando se esto a guardar dados

privados em campos no publicadas

opo

fields

para lhes aceder

argumento do selector do

dado que o utilizador poderia manipular a

e tamb

find()

m se deve evitar usar esta abordagem no

pelas mesmas raz

es de segurana

Uma abordagem mais segura poderia ser passar os parmetros individuais em vez do

objecto todo

para garantir que se tem controlo sobre os seus dados

Meteor.publish('posts', function(sort, limit) {


return Posts.find({}, {sort: sort, limit: limit});
});

Agora que estamos a subscrever ao n vel da rota

dados no mesmo lugar

funo

data

tamb

m faz sentido definir o contexto de

Vamos afastar nos um pouco da nossa abordagem anterior e fazer a

devolver um objecto JavaScript em vez de simplesmente devolver um cursor

Isto permite nos criar um contexto de dados com nome

O que isto significa

dentro do template

a que vamos chamar

posts .

simplesmente que em vez estar implicitamente dispon vel com o

o nosso contexto de dados vai estar dispon vel em

deste pequeno elemento

http://pt.discovermeteor.com/pdf

o c

this

posts . Para alm

digo dever ser familiar

204/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Router.map(function() {
this.route('postsList', {
path: '/:postsLimit?',
waitOn: function() {
var limit = parseInt(this.params.postsLimit) || 5;
return Meteor.subscribe('posts', {sort: {submitted: -1}, limit: limit}
);
},
data: function() {
var limit = parseInt(this.params.postsLimit) || 5;
return {
posts: Posts.find({}, {sort: {submitted: -1}, limit: limit})
};
}
});

//..
});

lib router js

Agora que estamos a definir o contexto de dados ao nivel do roteador podemos com

posts

segurana vermo nos livres do ajudante de template

dentro do ficheiro

posts_list.js . E dado que chammos ao nosso contexto de dados posts

),

do ajudante

nem precisamos de tocar no template

Vamos recapitular

Aqui est como o nosso c

postsList

digo do

router.js

o mesmo nome

novo e melhorado deve

parecer

http://pt.discovermeteor.com/pdf

205/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Router.configure({
layoutTemplate: 'layout',
loadingTemplate: 'loading',
waitOn: function() {
return [Meteor.subscribe('notifications')]
}
});
Router.map(function() {
//...

);

this.route('postsList', {
path: '/:postsLimit?',
waitOn: function() {
var limit = parseInt(this.params.postsLimit) || 5;
return Meteor.subscribe('posts', {sort: {submitted: -1}, limit: limit}

},
data: function() {
var limit = parseInt(this.params.postsLimit) || 5;
return {
posts: Posts.find({}, {sort: {submitted: -1}, limit: limit})
};
}
});
});

lib router js

Commit122

Rota postsList melhorada para receber um limite

Ver no GitHub

Lanar Instncia

Vamos experimentar o nosso novo sistema de paginao

Temos agora a habilidade de

mostrar um n

mero arbitrrio de artigos na pgina inicial simplesmente mudando o

parmetro de URL

algo como isto

Por exemplo

experimente aceder a

http://localhost:3000/3 . Deve ver

http://pt.discovermeteor.com/pdf

206/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Controlandoonmerodeartigosnapginainicial.

http://pt.discovermeteor.com/pdf

207/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Porquenopginas?
Porque

que estamos a usar uma abordagem de

mostrar pginas sucessivas com

resultados de pesquisas

Isto

10

artigos cada

paginao infinita

em vez de

como o Google faz com os

na realidade devido ao paradigma de tempo real

usado por Meteor

Posts

Vamos imaginar que estamos a paginar a nossa coleo de

de resultados paginados do Google

mostra os artigos

10

10 20.
a

usando o formato

e que estamos atualmente na pgina

2,

que

O que acontece se outro utilizador apaga qualquer um dos

artigos anteriores

Dados que a nossa aplicao

O artigo

10

de tempo real

9,

seria agora o artigo

e desapareceria de vista

estaria agora dentro do intervalo

.
11

o nosso conjunto de dados iria mudar

enquanto que o artigo

O resultado final seria que o utilizador de repente

veria os artigos mudar sem razo aparente

Mesmo que tolerssemos este problema de usabilidade

complicada de implementar por motivos t

coleo

paginao tradicional

s publicamos os artigos

10 20

Posts , mas como iriamos encontrar esses artigos no cliente

selecionar os artigos

10 20,
.
at

cnicos

Vamos voltar ao nosso exemplo anterior

dados que existem apenas

10

at

da

No se pode

artigos no total no

conjunto de dados do cliente

Uma soluo simples seria simplesmente publicar esses

depois fazer um

Posts.find()

40.

Temos agora

20

,
.
es

10 20,
at

e a outra pelos artigos

artigos carregados no cliente no total

de saber quais pertencem a qual subscrio

Por todas estas raz

Mas e se comearmos a ter mais

como vai acontecer em breve

Vamos supor que uma subscrio pede os artigos

at

artigos no servidor

no cliente para apanhar todos os artigos publicados

Isto funciona se tivermos apenas uma subscrio

que uma subscrio de artigos

10

30

sem forma nenhuma

paginao tradicional simplesmente no faz muito sentido ao

trabalhar com Meteor

http://pt.discovermeteor.com/pdf

208/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

CriandoumControladordeRota
var limit =

Pode ter reparado que estamos a repetir a linha

parseInt(this.params.postsLimit) || 5;
coded no

exatamente ideal

seguir o principio DRY

Isto no

duas vezes

ter o n

prio

Controladores de Rota

mero

sempre melhor

se tal for poss vel

hard

Um controlador de

simplesmente uma forma de agrupar caracter sticas de roteamento juntas num pacote

reutilizvel do qual qualquer rota pode herdar

mas dado que

m disso

No se repita a si pr

Vamos introduzir um novo aspeto do Iron Router

rota

Al

o fim do munda

Don t Repeat Yourself

vamos refatorizar as coisas

nica rota

mas vai ver no pr

Neste momento vamos apenas utiliz lo numa

ximo cap tulo como esta caracter stica vai ser

.
til

PostsListController = RouteController.extend({
template: 'postsList',
increment: 5,
limit: function() {
return parseInt(this.params.postsLimit) || this.increment;
},
findOptions: function() {
return {sort: {submitted: -1}, limit: this.limit()};
},
waitOn: function() {
return Meteor.subscribe('posts', this.findOptions());
},
data: function() {
return {posts: Posts.find({}, this.findOptions())};
}
});
Router.map(function() {
//...
this.route('postsList', {
path: '/:postsLimit?',
controller: PostsListController
});
});

lib router js

http://pt.discovermeteor.com/pdf

209/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Vamos passar por cada passo

Primeiro

estamos a criar o nosso controlador estendendo de

RouteController . Depois definimos a propriedade template

limit

Depois definimos uma nova funo

extra

que vai devolver um objecto de op

definimos as nossas fun

ltima coisa a fazer

.
es

e uma funo

Isto pode parecer como um passo

waitOn

es de

data

de

tal como antes

excepto que estas

findOptions .

vo agora usar as nossa nossa funo

Uma

que vai devolver o limite atual

mas vamos fazer uso dele mais tarde

A seguir

increment .

depois uma nova propriedade

findOptions

tal como fizemos antes

dizer rota

postsList

para rotear o nosso controlador novo

com

controller .

a propriedade

Commit123

Rota postsList refatorizada num RouteController

Ver no GitHub

Lanar Instncia

AdicionandoumLinkdeCarregarMais

Temos a paginao a funcionar

e o nosso c

digo tem bom aspeto

Existe s

um problema

no

existe nenhuma forma de de facto usar essa paginao excepto alterando o URL

manualmente

Isto definitivamente no

uma boa experi

ncia de utilizao

portanto vamos

ao trabalho de corrigir isto

O que queremos fazer

bastante simples

fundo da nossa lista de artigos

por

cada vez que

clicado

Vamos adicionar um boto de

que vai aumentar o n

Ou seja

http://localhost:3000/5 , clicar

carregar mais

no

mero de artigos atualmente mostrados

se atualmente estou no URL

carregar mais

deve trazer me para

http://localhost:3000/10 . Se chegou a este ponto no livro, confiamos que pode lidar com
alguma aritm

tica

http://pt.discovermeteor.com/pdf

210/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Como dantes

vamos adicionar a nossa l

gica de paginao no roteador

Lembra se quando

demos um nome explicito ao nosso contexto de dados em vez de simplesmente usar um

cursor anonimo

passar cursores

Bem

no existe nenhuma regra que diga que a funo

por isso vamos usar a mesma t

data

pode apenas

cnica para gerar o URL do nosso boto

carregar mais

PostsListController = RouteController.extend({
template: 'postsList',
increment: 5,
limit: function() {
return parseInt(this.params.postsLimit) || this.increment;
},
findOptions: function() {
return {sort: {submitted: -1}, limit: this.limit()};
},
waitOn: function() {
return Meteor.subscribe('posts', this.findOptions());
},
posts: function() {
return Posts.find({}, this.findOptions());
},
data: function() {
var hasMore = this.posts().count() === this.limit();
var nextPath = this.route.path({postsLimit: this.limit() + this.incremen
t});
return {
posts: this.posts(),
nextPath: hasMore ? nextPath : null
};
}
});

lib router js

Vamos olhar mais a fundo para este pedao de magia de roteador

postsList

que vai herdar do controlador

atualmente a trabalhar

Assim quando n

PostsListController

recebe um parmetro

s passamos

no qual estamos

postsLimit .

{postsLimit: this.limit() + this.increment}

this.route.path() , estamos a dizer rota postsList


usando esse objeto JavaScript como contexto de dados

http://pt.discovermeteor.com/pdf

Lembre se que a rota

ao

para construir o seu pr

prio caminho

.
211/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Noutras palavras

'postsList'}}

isto

{{pathFor

exatamente o mesmo que usar o ajudante

do Handlebars

excepto que estamos a substituir o

this

impl cito pelo nosso

contexto de dados feito medida

s estamos a usar esse caminho e a adicion lo ao contexto de dados para o nosso template

mas apenas se existirem mais artigos para mostrar

complicada

s sabemos que

mostrar

cont

this.limit()

devolve o n

que pode ou ser o valor no URL atual

algo

mero atual de artigos que gostar amos de

ou o nosso valor por omisso

(5)

se o URL no

m nenhum parmetro

, this.posts

Por outro lado

refere se ao cursor atual

se ao n

por isso

this.posts.count()

refere

mero de artigos que esto atualmente no cursor

O que estamos a dizer aqui

que se pedimos por

continuar a mostrar o boto de

que

A forma como fazemos isto

carregar mais

artigos e recebemos

Mas se pedimos por

de volta

vamos

e recebemos menos

n , ento isto significa que atingimos o limite e que temos de parar de mostrar esse

boto

Tendo dito isto

dados

o nosso sistema falha num caso

exatamente

mero de itens na nossa base de

n . Se isso acontecer, o cliente vai pedir n

volta e continuar a mostrar o boto

Infelizmente

quando o n

carregar mais

artigos e receber

artigos de

no sabendo que no existem mais itens

no existem formas simples de dar a volta a este problema

- -

e por agora vamos

ter de nos contentar com esta implementao menos que perfeita

Tudo o que resta fazer

garantindo que s

adicionar o link de

carregar mais

no funda da nossa lista de artigos

o mostramos se de facto existirem mais artigos para carregar

http://pt.discovermeteor.com/pdf

212/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

<template name="postsList">
<div class="posts">
{{#each posts}}
{{> postItem}}
{{/each}}
{{#if nextPath}}
<a class="load-more" href="{{nextPath}}">Load more</a>
{{/if}}
</div>
</template>

client views posts posts

Isto

list html

como a sua lista de artigos deve parecer agora

Obotodecarregarmais.

()

nextPath

Commit124
foi adicionado ao controlador e

Ver no GitHub

http://pt.discovermeteor.com/pdf

agora usado

Lanar Instncia

213/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

UmaMelhorBarradeProgresso

A nossa paginao est agora a funcionar perfeitamente

cada vez que carregamos

loading

template de

carregar mais

mas sofre de um problema irritante

e o roteador pede mais artigos

voltamos ao

enquando esperamos que os novos dados cheguem

O resultado

que

de cada vez somos enviados de novo para o topo da pgina e precisamos de fazer scroll at

ao

fundo para poder continuar a nossa navegao

Seria muito

muito melhor se pud

ssemos ficar na mesma pgina durante toda a operao

ao mesmo tempo providenciar algum tipo de indicao de que novos dados esto a ser

carregados

Felizmente

isto

precisamente o que o pacote

De forma semelhante ao Safari de iOS ou a sites como Medium e YouTube

progress

adiciona uma fina barra de carregamento ao topo do ecr

simples como adicionar o pacote sua aplicao

iron-router-progress

faz

, iron-router-

Implementar isto

to

mrt add iron-router-progress

consola bash

Atrav

s da magina dos pacotes inteligentes

perfeitamente ap

s instalar

o nosso novo indicador de progresso funciona

A barra de progresso vai ser ativada para cada rota

automaticamente completar assim que os dados de cada rota terminem de carregar

Vamos fazer apenas um pequeno ajuste

postSubmit

de contas

Vamos desligar

iron-router-progress

para a rota

dado que esta no precisa de esperar por nenhuns dados de subscrio

apenas um formulrio vazio

http://pt.discovermeteor.com/pdf

):

no final

214/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Router.map(function() {

//...
this.route('postSubmit', {
path: '/submit',
disableProgress: true
});
});

lib router js

Commit125

Usar o pacote iron router progress para fazer a paginao

Ver no GitHub

Lanar Instncia

AcedendoQualquerArtigo

Estamos atualmente a carregar os

algu

mais recentes por omisso

mas o que acontece quando

m navega para a pgina individual de um artigo

http://pt.discovermeteor.com/pdf

215/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Umtemplatevazio

Se tentar

vai ver um template de artigo vazio

subscrever publicao

agora

postsList , mas no lhe dissemos o que

ao carregar a rota

tudo o que sabemos fazer

pedimos ao servidor por um

consigo

subscrever a uma lista do

nico artigo espec fico

n ltimos artigos. Como

Vamos partilhar um pequeno segredo

poss vel ter mais que uma publicao para cada coleo

Ento para obter os nossos artigos em falta de volta

publicao nova

pelo

dissemos ao roteador para

postPage .

fazer com a rota

Mas at

posts

Isto faz sentido

separada

chamada

singlePost

vamos simplesmente fazer uma

que apenas publica um artigo

identificado

_id .

Meteor.publish('posts', function(options) {
return Posts.find({}, options);
});
Meteor.publish('singlePost', function(id) {
return id && Posts.find(id);
});

server publications js

Agora

vamos subscrever aos artigos corretos no lado do cliente

publicao

comments

na funo

adicionar a subscrio a

nossa subscrio rota

http://pt.discovermeteor.com/pdf

waitOn

singlePost

ai

da rota

J estamos a subscrever

postPage , por isso podemos simplesmente

E no nos vamos esquecer de tamb

m adicionar a

postEdit , uma vez que esta precisa dos mesmo dados:

216/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Router.map(function() {

//...
this.route('postPage', {
path: '/posts/:_id',
waitOn: function() {
return [
Meteor.subscribe('singlePost', this.params._id),
Meteor.subscribe('comments', this.params._id)
];
},
data: function() { return Posts.findOne(this.params._id); }
});
this.route('postEdit', {
path: '/posts/:_id/edit',
waitOn: function() {
return Meteor.subscribe('singlePost', this.params._id);
},
data: function() { return Posts.findOne(this.params._id); }
});
/...
});

lib router js

Commit126
Usar uma subscrio a um

Ver no GitHub

Com a paginao implementada

escalabilidade

nico artigo para garantir que p

Lanar Instncia

a nossa aplicao j no sofre de problemas de

pico do pr

e os utilizadores de certeza vo contribuir com ainda mais links que antes

seria ento bom ter uma forma qualquer de classificar esses links

ximo cap tulo

http://pt.discovermeteor.com/pdf

Votao

Isto

No

precisamente o

217/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Votao

13

Agora que o nosso site est ficando mais popular

complicado

O que n

s precisamos

encontrar os melhores links logo se tornar

de algum sistema de votao para ordenar nossos

artigos

s poder amos construir um sistema complexo de votao com karma

pontos baseado em tempo

em Telescope

e muitas outras coisas

).

o irmo mais velho do Microscope

decaimento de

muitas das quais foram implementadas

Mas para o nosso aplicativo

manteremos as coisas simples e apenas avaliaremos os artigos pelo n

,
n

mero de votos que eles

receberam

Vamos comear por dar aos usurios uma forma de votar nos artigos

ModelodeInformao

s armazenaremos a lista de upvoters de cada artigo para que n

o boto upvote para os usurios

http://pt.discovermeteor.com/pdf

s saibamos quando mostrar

assim como prevenir pessoas de votar duas vezes

218/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

PrivacidadedaInformao&Publicaes
N

s estaremos publicando essas listas de upvoters para todos usurios

o que

tamb

m tornar automaticamente toda essa informao publicamente acess vel

atrav

s do console do navegador

Este

o tipo de problema de privacidade de informao que pode surgir da forma

como as cole

es funcionam

Por exemplo

s queremos que pessoas sejam

capazes de encontrar quem votou em seus artigos

No nosso caso fazer essa

informao publicamente dispon vel no trar qualquer conseq

ncia

mas

importante ao menos reconhecer a questo

Tamb

m note que se n

s quis

ssemos restringir parte desta informao

ter amos de garantir que o cliente no possa burlar as op

publicao

es

fields

seja removendo essa propriedade pelo lado do servidor

,
n

da nossa

ou ao no

passar o objeto options completo do cliente pro servidor

s tamb

m desnormalizaremos o n

recepo dele

Ento n

mero total de upvoters no artigo para tornar mais fcil a

s estaremos adicionando dois atributos aos nossos artigos

votes . Vamos comear por adicion

los ao nosso arquivo de exemplos

, upvoters

// Fixture data
if (Posts.find().count() === 0) {
var now = new Date().getTime();
// create two users
var tomId = Meteor.users.insert({
profile: { name: 'Tom Coleman' }
});
var tom = Meteor.users.findOne(tomId);
var sachaId = Meteor.users.insert({
profile: { name: 'Sacha Greif' }
});
var sacha = Meteor.users.findOne(sachaId);
var telescopeId = Posts.insert({
title: 'Introducing Telescope',
userId: sacha._id,
author: sacha.profile.name,
url: 'http://sachagreif.com/introducing-telescope/',
http://pt.discovermeteor.com/pdf

219/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

submitted: now - 7 * 3600 * 1000,


commentsCount: 2,
upvoters: [], votes: 0
});
Comments.insert({
postId: telescopeId,
userId: tom._id,
author: tom.profile.name,
submitted: now - 5 * 3600 * 1000,
body: 'Interesting project Sacha, can I get involved?'
});
Comments.insert({
postId: telescopeId,
userId: sacha._id,
author: sacha.profile.name,
submitted: now - 3 * 3600 * 1000,
body: 'You sure can Tom!'
});
Posts.insert({
title: 'Meteor',
userId: tom._id,
author: tom.profile.name,
url: 'http://meteor.com',
submitted: now - 10 * 3600 * 1000,
commentsCount: 0,
upvoters: [], votes: 0
});
Posts.insert({
title: 'The Meteor Book',
userId: tom._id,
author: tom.profile.name,
url: 'http://themeteorbook.com',
submitted: now - 12 * 3600 * 1000,
commentsCount: 0,
upvoters: [], votes: 0
});
for (var i = 0; i < 10; i++) {
Posts.insert({
title: 'Test post #' + i,
author: sacha.profile.name,
userId: sacha._id,
url: 'http://google.com/?q=test-' + i,
submitted: now - i * 3600 * 1000,
commentsCount: 0,
upvoters: [], votes: 0
});
http://pt.discovermeteor.com/pdf

220/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

server fixtures js

Como de costume

pare seu aplicativo

nova conta de usurio

rode

Vamos ento tamb

meteor reset , reinicie seu aplicativo, e crie uma

m garantir que essas duas propriedades sejam

inicializadas quando nossos artigos forem criados

//...
// check that there are no previous posts with the same link
if (postAttributes.url && postWithSameLink) {
throw new Meteor.Error(302,
'This link has already been posted',
postWithSameLink._id);
}
// pick out the whitelisted keys
var post = _.extend(_.pick(postAttributes, 'url', 'title', 'message'), {
userId: user._id,
author: user.username,
submitted: new Date().getTime(),
commentsCount: 0,
upvoters: [],
votes: 0
});
var postId = Posts.insert(post);
return postId;

//...

collections posts js

ConstruindonossosTemplatesdeVotao

Primeiro

s adicionaremos um boto upvote a nossa parcial artigo

http://pt.discovermeteor.com/pdf

221/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

<template name="postItem">
<div class="post">
<a href="#" class="upvote btn"></a>
<div class="post-content">
<h3><a href="{{url}}">{{title}}</a><span>{{domain}}</span></h3>
<p>
{{votes}} Votes,
submitted by {{author}},
<a href="{{pathFor 'postPage'}}">{{commentsCount}} comments</a>
{{#if ownPost}}<a href="{{pathFor 'postEdit'}}">Edit</a>{{/if}}
</p>
</div>
<a href="{{pathFor 'postPage'}}" class="discuss btn">Discuss</a>
</div>
</template>

/ _

client views posts post

item html

Theupvotebutton

Em seguida

s chamaremos um M

todo upvote do servidor quando o usurio clicar no

boto

http://pt.discovermeteor.com/pdf

222/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

//...
Template.postItem.events({
'click .upvote': function(e) {
e.preventDefault();
Meteor.call('upvote', this._id);
}
});

/ _

client views posts post

Finalmente

item js

s voltaremos ao nosso arquivo

collections/posts.js

todo Meteor do lado do servidor que ir upvote os artigos

e adicionaremos o

Meteor.methods({
post: function(postAttributes) {
//...
},
upvote: function(postId) {
var user = Meteor.user();
// ensure the user is logged in
if (!user)
throw new Meteor.Error(401, "You need to login to upvote");
var post = Posts.findOne(postId);
if (!post)
throw new Meteor.Error(422, 'Post not found');
if (_.include(post.upvoters, user._id))
throw new Meteor.Error(422, 'Already upvoted this post');

}
});

Posts.update(post._id, {
$addToSet: {upvoters: user._id},
$inc: {votes: 1}
});

collections posts js

http://pt.discovermeteor.com/pdf

223/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Commit131

Added basic upvoting algorithm

Ver no GitHub

Este M

todo

bem linear

Lanar Instncia

s fazemos algumas verifica

usurio est logado e que o artigo realmente existe

votou neste artigo

es defensivas para assegurar que o

Ento n

s checamos se o usurio j no

e se ele no o tiver feito n

s incrementamos o n

mero total de votos e

adicionamos o usurio a lista de upvoters

Este passo final

interessante

muito mais a se aprender

j que n

s usamos alguns operadores Mongo especiais

mas estes dois so extremamente

tem a uma propriedade array desde que ela j no exista

um campo de inteiro

: $addToSet

teis

$inc

adiciona um

simplesmente incrementa

TruquesnaInterfacedoUsurio

Se o usurio no est logado

refletir isso na nossa UI

classe CSS

disabled

ou j votou num artigo

eles no sero capazes de votar

Para

s usaremos um ajudante para condicionalmente adicionar uma

ao boto upvote

<template name="postItem">
<div class="post">
<a href="#" class="upvote btn {{upvotedClass}}"></a>
<div class="post-content">
//...
</div>
</template>

/ _

client views posts post

http://pt.discovermeteor.com/pdf

item html

224/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Template.postItem.helpers({
ownPost: function() {
//...
},
domain: function() {
//...
},
upvotedClass: function() {
var userId = Meteor.userId();
if (userId && !_.include(this.upvoters, userId)) {
return 'btn-primary upvotable';
} else {
return 'disabled';
}
}
});
Template.postItem.events({
'click .upvotable': function(e) {
e.preventDefault();
Meteor.call('upvote', this._id);
}
});

/ _

client views posts post

item js

s estamos mudando nossa classe de

.upvote

para

.upvotable , ento no se esquea de

mudar o manuseador de evento clique tamb

http://pt.discovermeteor.com/pdf

225/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Greyingoutupvotebuttons.

Commit132
Grey out upvote link when not logged in

Ver no GitHub

Em seguida

voc

mas por hora n

already voted

nico voto esto escritos

rico que n

votos

ento

Pluralizao pode ser um processo complicado

s faremos de uma forma razoavelmente simples

Handlebars gen

Lanar Instncia

pode notar que artigos com um

vamos cuidar de pluraliz los corretamente

s podemos usar em qualquer lugar

s faremos um ajudante

Handlebars.registerHelper('pluralize', function(n, thing) {


// fairly stupid pluralizer
if (n === 1) {
return '1 ' + thing;
} else {
return n + ' ' + thing + 's';
}
});

http://pt.discovermeteor.com/pdf

226/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

client helpers handlebars js

Os ajudantes que n

eles se aplicavam

s criamos antes estavam ligados a um administrador e template ao qual

Mas ao utilizar

Handlebars.registerHelper , ns criamos um ajudante

global que pode ser utilizado dentro de qualquer template

<template name="postItem">
//...
<p>
{{pluralize votes "Vote"}},
submitted by {{author}},
<a href="{{pathFor 'postPage'}}">{{pluralize commentsCount "comment"}}</a>
{{#if ownPost}}<a href="{{pathFor 'postEdit'}}">Edit</a>{{/if}}
</p>
//...
</template>

/ _

client views posts post

item html

PerfectingProperPluralization(nowsaythat10times)

http://pt.discovermeteor.com/pdf

227/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Commit133
Added pluralize helper to format text better

Ver no GitHub

s devemos agora ver

vote

Lanar Instncia

AlgoritmodeVotaomaisinteligente

Nosso c

digo de votao est com uma cara boa

todo upvote

,
n

para atualiz lo

s fazemos duas chamadas ao Mongo

es pertinentes a isso

dados duas vezes

2.
3.

Primeiramente

Por

m ainda mais importante

estamos seguindo o seguinte algoritmo

1.

s ainda podemos fazer melhor

um para pegar o artigo

No

ento outra

H duas quest

mas n

um tanto ineficiente ir ao banco de

isso introduz uma condio de corrida

:
.

Pegar um artigo do banco de dados

Checar se o usurio votou

Caso contrrio

faa um voto pelo usurio

E se o mesmo usurio votasse de novo entre as etapas

1 3
e

para o usurio ser capaz de votar no mesmo artigo duas vezes

ser mais inteligente e combinar as etapas

http://pt.discovermeteor.com/pdf

13

Nosso c

digo atual abre a porta

Felizmente

Mongo nos permite

num simples comando Mongo

228/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Meteor.methods({
post: function(postAttributes) {
//...
},
upvote: function(postId) {
var user = Meteor.user();
// ensure the user is logged in
if (!user)
throw new Meteor.Error(401, "You need to login to upvote");

}
});

Posts.update({
_id: postId,
upvoters: {$ne: user._id}
}, {
$addToSet: {upvoters: user._id},
$inc: {votes: 1}
});

collections posts js

Commit134

Better upvoting algorithm

Ver no GitHub

O que n

s estamos dizendo

ainda no votou

encontre todos os artigos com este

e atualize os desta forma

encontrar o artigo com essa

nica desvantagem

onde o este usurio

j votou

e consequentemente nada ocorrer

que agora n

j que n

id

Se o usurio no votou ainda

id . Por outro lado se o usurio

encontrar nenhum documento

Lanar Instncia

claro que ele

ento a consulta no

s no podemos dizer ao usurio que ele j votou no artigo

).

s nos livramos da chamada ao banco de dados que checava isso

saber disso pelo o boto

http://pt.discovermeteor.com/pdf

upvote

estar desativado na interface do usurio

Mas eles devem

229/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

CompensaodeLatncia
Vamos dizer que voc

tentou roubar e enviou um dos seus artigos para o topo da lista

modificando o n

mero de votos

> Posts.update(postId, {$set: {votes: 10000}});


Browser console

onde

postId a id de um seus artigos

Esta tentativa descarada de burlar o sistema seria pega pela nossa callback

em

?)

collections/posts.js , lembra

Mas se voc

olhar cuidadosamente

lat

ncia em ao

Pode ser veloz

voc

deny()

e imediatamente negada

pode ser capaz de ver a compensao de

mas o artigo brevemente saltar para o topo da

lista antes de voltar a sua posio

O que aconteceu

incidente

Na nossa coleo

Posts

Isto ocorre instantaneamente

Enquanto isso

no servidor

update

contado em milissegundos se voc

retornou um error

O resultado final

local

update

foi aplicado sem

ento o artigo disparou para o topo da lista

foi negado

Ento algum tempo mais tarde

),

est rodando Meteor na sua mquina

o servidor

deixando a coleo local se reverter sozinha

enquanto se espera o servidor responder

no pode fazer nada al

negar a modificao

m de confiar na coleo local

a interface do usurio

Assim que o servidor voltar e

a interface do usurio se atualiza para refletir isso

RanqueandoosArtigosdaPginaPrincipal

Agora que n

s temos uma pontuao para cada artigo baseada no n

mostrar uma lista dos artigos mais votados

Para tanto

assinaturas separadas contra a coleo de artigo

,
n

mero de votos

vamos

s veremos como administrar duas

e fazer no nosso template

postsList

um

pouco mais geral

Para comear

,
n

s queremos ter duas assinaturas

http://pt.discovermeteor.com/pdf

uma para cada organizao

O truque aqui

230/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

posts , porm com

que ambas assinaturas iro assinar para a mesma publicao

argumentos diferentes

s tamb

URLs

m criaremos duas novas rotas chamadas

/new

).

/best

respecitvamente

junto com

newPosts

/new/5

bestPosts , acessvel nas

/best/5

para nossa paginao

claro

Para fazer isso

distintos

s iremos estender nosso

NewPostsListController

PostsListController

nico

NewPostsListController

BestPostsListController . Isto ns permitir re

utilizar a exata mesma opo de rota tanto para a rota

ao nos dar um

em dois controladores

home

quanto para a rota

do qual herdar

newPosts ,

E adicionalmente

apenas

uma boa ilustrao de quo flex vel o Iron Router pode ser

PostsListController = RouteController.extend({
template: 'postsList',
increment: 5,
limit: function() {
return parseInt(this.params.postsLimit) || this.increment;
},
findOptions: function() {
return {sort: this.sort, limit: this.limit()};
},
waitOn: function() {
return Meteor.subscribe('posts', this.findOptions());
},
posts: function() {
return Posts.find({}, this.findOptions());
},
data: function() {
var hasMore = this.posts().fetch().length === this.limit();
return {
posts: this.posts(),
nextPath: hasMore ? this.nextPath() : null
};
}
});
NewPostsListController = PostsListController.extend({
sort: {submitted: -1, _id: -1},
nextPath: function() {
return Router.routes.newPosts.path({postsLimit: this.limit() + this.incr
ement})
}
});
http://pt.discovermeteor.com/pdf

231/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

BestPostsListController = PostsListController.extend({
sort: {votes: -1, submitted: -1, _id: -1},
nextPath: function() {
return Router.routes.bestPosts.path({postsLimit: this.limit() + this.inc
rement})
}
});
Router.map(function() {
this.route('home', {
path: '/',
controller: NewPostsListController
});
this.route('newPosts', {
path: '/new/:postsLimit?',
controller: NewPostsListController
});
this.route('bestPosts', {
path: '/best/:postsLimit?',
controller: BestPostsListController
});
// ..
});

lib router js

Note que agora que n

s temos mais de uma rota

PostsListController

e para dentro de

s tiramos a l

gica

NewPostsListController

nextPath

para fora do

BestPostsListController , j que o caminho ser diferente em qualquer um dos casos.

Adicionalmente

quando n

votes , ns temos uma organizao

s organizamos por

secundria por timestamp submetida para assegurar que a ordem est correta

s tamb

m adicionaremos links no cabealho

http://pt.discovermeteor.com/pdf

232/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

<template name="header">
<header class="navbar">
<div class="navbar-inner">
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-col
lapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<a class="brand" href="{{pathFor 'home'}}">Microscope</a>
<div class="nav-collapse collapse">
<ul class="nav">
<li>
<a href="{{pathFor 'newPosts'}}">New</a>
</li>
<li>
<a href="{{pathFor 'bestPosts'}}">Best</a>
</li>
{{#if currentUser}}
<li>
<a href="{{pathFor 'postSubmit'}}">Submit Post</a>
</li>
<li class="dropdown">
{{> notifications}}
</li>
{{/if}}
</ul>
<ul class="nav pull-right">
<li>{{loginButtons}}</li>
</ul>
</div>
</div>
</header>
</template>

client views include header html

Com tudo isso feito

http://pt.discovermeteor.com/pdf

s agora ganhamos uma lista de melhores artigos

233/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Rankingbypoints

Commit135

Added routes for post lists

and pages to display them

Ver no GitHub

Lanar Instncia

UmCabealhoMelhor

Agora que n

atualmente

s temos duas pginas de artigos

Ento vamos revisitar nosso cabealho para fazer isto

header.js

administrador

A razo para n

s querermos suportar m

newPosts

mesmo template

para fazer a tag

bvio

.
N

s criaremos um

tens de navegao

ltiplas rotas nomeadas

Significando que nossa

http://pt.discovermeteor.com/pdf

as quais correspondem s URLs

<li>

est vendo

e criaremos um ajudante que usa o caminho atual e uma ou mais

rotas nomeadas para configurar uma classe ativa nos nossos

home

pode ser dif cil saber qual lista voc

/new

activeRouteClass

ativa em ambos os casos

que tanto nossas rotas

respectivamente

chamam o

deve ser inteligente o suficiente

234/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

<template name="header">
<header class="navbar">
<div class="navbar-inner">
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-col
lapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<a class="brand" href="{{pathFor 'home'}}">Microscope</a>
<div class="nav-collapse collapse">
<ul class="nav">
<li class="{{activeRouteClass 'home' 'newPosts'}}">
<a href="{{pathFor 'newPosts'}}">New</a>
</li>
<li class="{{activeRouteClass 'bestPosts'}}">
<a href="{{pathFor 'bestPosts'}}">Best</a>
</li>
{{#if currentUser}}
<li class="{{activeRouteClass 'postSubmit'}}">
<a href="{{pathFor 'postSubmit'}}">Submit Post</a>
</li>
<li class="dropdown">
{{> notifications}}
</li>
{{/if}}
</ul>
<ul class="nav pull-right">
<li>{{loginButtons}}</li>
</ul>
</div>
</div>
</header>
</template>

client views includes header html

http://pt.discovermeteor.com/pdf

235/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Template.header.helpers({
activeRouteClass: function(/* route names */) {
var args = Array.prototype.slice.call(arguments, 0);
args.pop();
var active = _.any(args, function(name) {
return Router.current().route.name === name
});
}
});

return active && 'active';

client views includes header js

Showingtheactivepage

http://pt.discovermeteor.com/pdf

236/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

ArgumentosdeAjudantes
N

s no usamos esse padro espec fico at

tag de Handlerbar

E como voc

voc

tamb

receb

Neste

agora

mas assim como qualquer outra

tags de templates ajudantes podem receber argumentos

pode claro passar argumentos nomeados espec ficos para sua funo

m pode passar um n

los ao chamar o objeto

ltimo caso

voc

mero no especificado de parmetros an

arguments

nimos e

dentro de uma funo

provavelmente gostar de converter o objeto

um array JavaScript regular e ento chamar

pop()

arguments

em

para se livrar da hash adicionada

ao fim pelo Handlebars

Para cada

rota

teste

tem de navegao

e ento usa o ajudante

o ajudante

any()

activeRouteClass

recebe uma lista de nomes de

do Underscore para ver se alguma das rotas passa no

).

vulgo a URL correspondente ser igual ao caminho atual

, any()

Se qualquer uma das rotas corresponder com o caminho atual

Finalmente

&& myString

s estamos fazendo uso do padro JavaScript

retorna

false , mas true && myString

retornar

boolen && string

true .

onde

false

myString .

retorna

Commit136

Added active classes to the header

Ver no GitHub

Lanar Instncia

Agora que usurios podem votar em artigos em tempo real

e para baixo na nossa homepage quando os ranks mudam

uma forma de suavizar tudo isso com algums anima

http://pt.discovermeteor.com/pdf

voc

ver

tens pulando para cima

Mas no seria legal se houvesse

es no momento certo

237/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

PublicaesAvanadas

Agora voc

13.5

SIDEBAR

j deve ter entendido como publica

es e assinaturas interagem

livrar das rodinhas e examinar alguns cenrios mais avanados

Ento vamos nos

PublicandoumaColeoMltiplasVezes

Na nossa primeira barra lateral sobre publica

comuns de publicao e assinatura

e n

,
es

s aprendemos como a funo

vamos lembrar o que

_publishCursor

faz para n

s exatamente

ela pega todos os

Note que o nome da publicao no est de forma alguma envolvido

s podemos ter mais de uma publicao ligando as vers

servidor de qualquer coleo

es do cliente e do

os fez

e os puxam para a coleo do lado do

Isto significa que n

_publishCursor

es mais

prios sites

documentos que combinam com um dado cursor

cliente do mesmo nome

s vimos alguns dos padr

bem fceis de implementar nos nossos pr

Primeiro

s j encontramos esse padro no nosso cap tulo sobre paginao

quando n

s publicamos

um subconjunto paginado de todos os artigos em adio ao artigo atualmente disposto

.
,

Outro caso similar seria publicar uma viso geral de um conjunto grande de documentos

assim como os detalhes completos de um

http://pt.discovermeteor.com/pdf

nico

tem

238/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Publishingacollectiontwice

Meteor.publish('allPosts', function() {
return Posts.find({}, {fields: {title: true, author: true}});
});
Meteor.publish('postDetail', function(postId) {
return Posts.find(postId);
});

Agora quando o cliente assina essas duas publica

postId

correto est sendo enviado assinatura

povoada por duas fontes

es

usando

autorun

para assegurar que o

postDetail , sua coleo 'posts'

fica

uma lista de t tulos e nomes de autor da primeira assinatura

e os

detalhes completos de um artigo da segunda

http://pt.discovermeteor.com/pdf

239/261

1/8/2015
Voc

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

por

pode perceber que o artigo publicado por

allPosts

postDetail

tamb

m est sendo publicado

apesar que apenas com um subconjunto de suas propriedades

).

Entretanto

Meteor toma conta de fundir os campos e assegurar que no haja nenhum artigo duplicado

Isto

timo

porque agora quando n

s renderizamos a lista de resumo dos artigos

,
n

estamos lidando com objetos de informao que que tem a exata quantidade de informao

para n

artigo

s mostrarmos o que precisamos

Entretanto

nico

quando n

s temos tudo o que precisamos para mostr la

s renderizamos a pgina de um

Claro

s precisamos tomar

conta no cliente para no se esperar todos os campos estarem dispon veis de todos os artigos

neste caso

isto

uma pegadinha comum

Deve ser notado que voc

no est limitado a variar as propriedades dos documentos

poderia normalmente publicar as mesmas propriedades em ambas publica

organizar os

es

Voc

mas

tens diferentemente

Meteor.publish('newPosts', function(limit) {
return Posts.find({}, {sort: {submitted: -1}, limit: limit});
});
Meteor.publish('bestPosts', function(limit) {
return Posts.find({}, {sort: {votes: -1, submitted: -1}, limit: limit});
});

server publications js

AssinandoumaPublicaoMltiplasVezes

s acabamos de ver como voc

pode publicar uma

nica coleo mais de uma vez

pode conseguir um resultado bem similar com outro padro

assin la m

ltiplas vezes

s assinamos publicao

configura e desfaz cada assinatura para n

assinar m

nica publicao

mas

Em Microscope

criar uma

Alis voc

posts

Por

ltiplas vezes

mas Iron Router

m no h razo para que n

s no possamos

ltiplas vezes simultaneamente

http://pt.discovermeteor.com/pdf

240/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Por exemplo

na mem

vamos dizer que n

ria ao mesmo tempo

s gostar amos de ler ambos os artigos mais novos e melhores

Subscribingtwicetoonepublication

s estamos configurando uma

nica publicao

Meteor.publish('posts', function(options) {
return Posts.find({}, options);
});

E n

s ento assinamos publicao m

ltiplas vezes

Na verdade isto

mais ou menos

exatamente o que estamos fazendo em Microscope

http://pt.discovermeteor.com/pdf

241/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Meteor.subscribe('posts', {submitted: -1, limit: 10});


Meteor.subscribe('posts', {baseScore: -1, submitted: -1, limit: 10});

Ento o que est acontecendo exatamente

diferentes

Cada navegador est abrindo duas assinaturas

cada uma conectando se a mesma publicao do servidor

Cada assinatura prov

um conjunto

argumentos diferentes publicao

diferente

de documentos

coleo do lado do cliente

mas fundamentalmente

puxado da coleo

posts

cada vez

e enviado pela rede

MltiplasColeesnumanicaAssinatura

Diferente de bancos de dados tradicionais relacionais como MySQL que trabalham com joins

jun

es

),

bancos de dados NoSQL como o Mongo so baseados em desnormalizao e

embutimento

Vamos ver como isso funciona no contexto do Meteor

Vamos ver um exemplo concreto

s adicionamos comentrios aos nossos artigos

agora

s estivemos contentes com publicar apenas os comentrios no artigo

e at

nico que o

usurio est observando

Entretanto

supomos que n

primeira pgina

s gostar amos de mostrar comentrio em todos os artigos da

tendo em mente que esses artigos vo mudar aos paginarmos atrav

Este cenrio de uso apresenta uma boa razo para embutir comentrios nos artigos

verdade

o que nos levou as desnormalizar a contagem de comentrios

Claro que n

coleo

Desnormalizao

Mas como n

ao fazer tanto n

com cole

de uma vez por todas

s deles

).

e na

s poder amos sempre apenas embutir os comentrios nos artigos

Comments

nos livrando da

s vimos previamente no cap tulo

s perder amos alguns dos benef cios extras de se trabalhar

es separadas

Mas alis h um truque envolvendo assinaturas que torna poss vel embutir nossos

comentrios enquanto preservamos cole

http://pt.discovermeteor.com/pdf

es separadas

242/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Vamos supor que junto com a nossa lista de artigos da pgina inicial

,
n

s gostar amos de

assinar a uma lista dos dois comentrios superiores de cada artigo

Seria dif cil conseguir isso com uma publicao de comentrios independente

se a lista de artigos fosse limitada de alguma forma

vamos dizer

os

10

especialmente

).

mais recentes

ter amos de escrever uma publicao que se parecesse com algo assim

Twocollectionsinonesubscription

Meteor.publish('topComments', function(topPostIds) {
return Comments.find({postId: topPostIds});
});

http://pt.discovermeteor.com/pdf

243/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Isso seria um problema de um ponto de vista de performance

j que a publicao precisaria

topPostIds

ser desfeita e re estabelecida cada vez que a lista de

H um jeito de se resolver isso alis

mudasse

.
N

mais de uma publicao por coleo

s apenas usamos o fato que no s

mas n

s podemos ter

s tamb

m podemos ter mais de uma coleo por

publicao

Meteor.publish('topPosts', function(limit) {
var sub = this, commentHandles = [], postHandle = null;

// send over the top two comments attached to a single post


function publishPostComments(postId) {
var commentsCursor = Comments.find({postId: postId}, {limit: 2});
commentHandles[post._id] =
Meteor.Collection._publishCursor(commentsCursor, sub, 'comments');
}
postHandle = Posts.find({}, {limit: limit}).observeChanges({
added: function(id, post) {
publishPostComments(post._id);
sub.added('posts', id, post);
},
changed: function(id, fields) {
sub.changed('posts', id, fields);
},
removed: function(id) {
// stop observing changes on the post's comments
commentHandles[id] && commentHandles[id].stop();
// delete the post
sub.removed('posts', id);
}
});
sub.ready();

// make sure we clean everything up (note `_publishCursor`


// does this for us with the comment observers)
sub.onStop(function() { postsHandle.stop(); });
});

Note que n

s no estamos retornando nada nesta publicao

enviamos mensagens ao

precisamos pedir a

sub

s mesmos

_publishCursor

http://pt.discovermeteor.com/pdf

via

para faz

.added()

lo por n

j que n

e amigos

).

s manualmente

Ento n

s no

s ao retornar um cursor

244/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Agora

cada vez que n

s publicamos um artigo n

dois comentrios superiores anexados a ele

s tamb

m automaticamente publicamos os

E tudo com uma

Apesar do Meteor ainda no fazer esse processo bem linear

pacote

publish-with-relations

no Atmosphere

nica chamada de assinatura

voc

pode tamb

m checar o

o qual busca fazer esse padro mais fcil

Ligandocoleesdiferentes

O que mais pode nosso conhecimento rec

se n

s no usamos o

m descoberto das assinaturas fazer por n

Bem

_publishCursor , ns no precisamos seguir as restries que a coleo

fonte no servidor precisa para ter o mesmo nome como alvo na coleo no cliente

Onecollectionfortwosubscriptions
http://pt.discovermeteor.com/pdf

245/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Uma razo para porque n

Suponha que n

s gostar amos de fazer isso

Herana de Tabela nica

s gostar amos de referenciar vrios tipos de objetos dos nossos artigos

cada

um deles armazenando campos em comum mas tamb

conte

do

Por exemplo

s poder amos estar construindo um mecanismo de blog como o

Tumblr onde cada artigo possui a clssica ID

tamb

m ter uma imagem

video

link

timestamp

ou apenas texto

s poder amos armazenar todas esses objetos numa

E apesar que n

mas em adio pode

nica coleo

para indicar que tipo de objeto eles so

s ter amos uma

transformar essa

'resources' , usando

. video , image , link ,

type

um atributo

e t tulo

m ligeiramente diferentes em

nica coleo

nica coleo em m

Resources

ltiplas cole

es

no servidor

..

etc

s poder amos

Videos , Images , etc. no cliente com o

tantinho de mgica seguinte

Meteor.publish('videos', function() {
var sub = this;
var videosCursor = Resources.find({type: 'video'});
Meteor.Collection._publishCursor(videosCursor, sub, 'videos');

// _publishCursor doesn't call this for us in case we do this more than


once.
sub.ready();
});

_publishCursor

s estamos dizendo ao

o cursor faria

publicar de

mas ao inv

'resources'

uma boa fazer isso

para publicar nossos v deos

s de publicar a coleo

para

resources

assim como retornar

para o cliente

s podemos

'videos' .

No cabe a nos julgar

Em qualquer caso

bom saber o que

poss vel

para se poder usar o Meteor ao mximo

http://pt.discovermeteor.com/pdf

246/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Animaes

14

s agora temos votao

contagem e ranque em tempo real

Entretanto

isto leva a uma

experi

ncia do usurio errtica e chocante j que os artigos pipocam na homepage

usaremos anima

es para suavizar isso

Meteor&oDOM

Antes de podermos comear a parte divertida

entender como o Meteor interage com o DOM

elementos HTML que produzem os conte

O ponto crucial a se manter em mente

apenas ser deletados e criados

).

Meteor

(
(

Document Object Model

).

s precisamos

a coleo de

que os elementos no podem ser movidos

note que isto

uma limitao do pr

prio DOM

nova posio

es

pia

( ')
B

antes do elemento A

ao mov

Para trocar os artigos A e B

j que no se pode simplesmente animar B at

sabemos que acontece instantaneamente

'

Eles podem

Meteor na

porque B desaparecer assim que o Meteor re renderizar a pgina

m criado B

no do

Ento para dar a iluso dos elementos A e B estarem trocando de lugar

Isto torna complicado fazer anima

dos de uma pgina

verdade deletar o elemento B e inserir uma nova c

o rec

),

fazer as coisas se moverem

).

graas reatividade

Ento

voc

o que

tem que animar

lo da posio do B antigo para sua nova posio antes de A

posicionados nas posi

es p

2,

e p

uma

),

respectivamente

seguir amos os seguintes passos

1.
2.
3.
4.
5.
6.

Delete B

'

Crie B

antes de A no DOM

Mova B

'

para p

Mova A para p

Anime A para p

'

Anime B para p

http://pt.discovermeteor.com/pdf

247/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

O seguinte diagrama explica esses passos em mais detalhe

http://pt.discovermeteor.com/pdf

248/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Swtichingtwoposts

Note que nos passos

teletransportando

3 4
e

s no estamos animando A e B

eles para l instantaneamente

que B nunca foi deletado

'

para suas posi

J que isto

es mas

instantneo

dar a iluso de

e posicionar apropriadamente ambos elementos para serem

animados de volta a suas novas posi

Felizmente

o Meteor toma conta dos passos

preocupar quanto aos passos

Al

m disso

5 6

nos passos

devidos lugares

passos

es

3 4,

Para que a

ao

para n

ento n

s apenas precisamos nos

6.

tudo que n

1&2

s estamos fazendo

mover os elementos para seus

nica parte que n

s realmente precisemos nos preocupar seja os

vulgo enviar os elementos para o ponto de in cio da animao

TimingCerto

At

agora n

3 4,

Para os passos

no nosso caso

5 6
e

a resposta

na callback de template

no mesmo lugar

minutos

minutos

se voc

dissesse a um

e ento quando isso

ele provavelmente deduziria que j que ele terminar

ele pode simplesmente salvar energia e no andar

quer garantir que seu andr

tem de esperar at

ide ande durante os

que ele ande os primeiros

O navegador funciona de uma forma similar

simultaneamente

Pense os dessa forma

gico para andar para o norte por

terminar andar para o sul por

aconteceria

so um pouco mais complicados

do Meteor dentro do

).

ide perfeitamente l

Ento se voc

rendered

ranque

andr

post_item.js , a qual ativada toda vez que uma propriedade do artigo muda

administrador

Os passos

s falamos sobre como animar nossos artigos mas no sobre quando anim los

minutos

10

minutos completos

e ento diz

lo para voltar

se n

voc

s simplesmente dermos a ele as intru

es

as novas coordenadas simplesmente substituiriam as antigas e nada

Em outras palavras

o navegador precisa registrar as mudanas na posio como

dois pontos separados no tempo

http://pt.discovermeteor.com/pdf

caso contrrio ele no ser capaz de anim los

249/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

O Meteor no prov

justAfterRendered , mas ns podemos falsific

uma callback

la usando

Meteor.defer() , a qual simplesmente recebe uma funo e adia sua execuo apenas o

suficiente para registr la como um evento diferente

PosicionamentoCSS

Para animar os artigos sendo reordenados na pgina

territ

rio CSS

s teremos de nos aventurar em

Um review rpido de posicionamento CSS pode ser necessrio

Elementos numa pgina usam posicionamento esttico por padro

posicionados se encaixam no fluxo da pgina

mudadas ou animadas

Elementos estaticamente

e suas coordenadas na pgina no podem ser

Posicionamento relativo por outro lado significa que o elemento tamb

da pgina

m se encaixa no fluxo

mas pode ser posicionado relativamente a sua posio original

Posicionamento absoluto vai um passo mais adiante e deixa voc

dar ao elemento

coordenadas x y espec ficas relativas ao documento ou ao primeiro elemento paterno

posicionado absoluta

relativamente

s utilizaremos posicionamento relativo para animar nossos artigos

das CSS para voc

mas se voc

seria adicionar este c

precisasse fazer voc

digo s suas folhas de estilo

.
N

s j tomamos conta

mesmo tudo que voc

precisaria fazer

.post{
position:relative;
transition:all 300ms 0ms ease-in;
}

client stylesheets style css

Isto faz os passos

5 6

seu valor padro

bem fceis

tudo que n

s precisamos fazer

configurar

e nossos artigos escorrero de volta a suas posi

http://pt.discovermeteor.com/pdf

es

top

para

0px

normais

250/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Isto significa que nosso

nico desafio

relao a suas novas posi

muito dif cil tamb

es

descobrir para onde anim los dos

Em outras palavras

o contrabalano correto

passos

como contrabalance los

simplesmente a posio pr

3 4
e

em

Mas isto no

via do artigo

menos sua nova

Posio:absoluta
N

s poder amos tamb

posicionar nossos elementos

absolutamente

position:absolute

m usar

com um pai relativo para

Mas a grande desvantagem de elementos posicionados

que eles esto completamente removidos do fluxo da pgina

causando o colapso de seu container paterno como se ele estivesse vazio

Isso ento significa que n

container via JavaScript

naturalmente

s precisar amos artificialmente configurar a altura do

ao inv

s de deixar o navegador refluir os elementos

Consequentemente

sempre que poss vel

melhor ficar com

posicionamento relativo

RecordaoTotal

s temos mais um problema ainda

lembrar

sua posio pr

com sua mem

via

Enquanto o elemento A persiste no DOM e pode ento

'

o elemento B experiencia reencarnao e volta vida como B

ria completamente vazia

Felizmente o Meteor vem nos resgastar nos dando acesso ao objeto instncia do template na

rendered . Como a documentao do Meteor afirma:

callback

, this

No corpo da callback

um objeto da instncia do template que

ocorr

s faremos

recriado

Desta forma

s ainda saberemos de onde n

http://pt.discovermeteor.com/pdf

es

encontrar a posio atual do artigo na pgina

no objeto de instncia do template

nico a esta

ncia do template e persiste ao longo de re renderiza

Ento o que n

mesmo quando o artigo

e ento armazen la

deletado e

s devemos anim lo

251/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Instncia do template tamb

m nos deixa acessar a informao da coleo atrav

s da

data . Isto ser til para pegar o ranque do artigo.

propriedade

RanqueandoArtigos

s estivemos falando sobre ranque de artigos

uma propriedade do artigo

listados na nossa coleo

j que

mas este

uma conseq

ranque

no existe de fato como

ncia da ordem na qual os artigos so

Se n

s quisermos animar os artigos de acordo com seu ranque

teremos que de alguma forma conjurar esta propriedade do nada

Note que n

o raque

s no podemos por essa propriedade

ranque

no pr

uma propriedade relativa que depende em como voc

prio banco de dados

organiza seus artigos

um artigo pode ser ranqueado primeiro quando organizado por data

organizado por pontos

).

s idealmente por amos essa propriedade nas nossas cole

es

j que

vulgo

mas terceiro quando

newPosts

topPosts , mas

o Meteor ainda no oferece um mecanismo conveniente para fazer isso

Ento

rank

s inseriremos

no

ltimo passo poss vel

o administrador de template

postList :

Template.postsList.helpers({
postsWithRank: function() {
this.posts.rewind();
return this.posts.map(function(post, index, cursor) {
post._rank = index;
return post;
});
}
});

client views posts posts

list js

Ao inv

s de simplesmente retornar o cursor

limit: postsHandle.limit()})

como nosso ajudante pr

recebe o cursor e adiciona a propriedade

http://pt.discovermeteor.com/pdf

Posts.find({}, {sort: {submitted: -1},

_rank

vio

posts , postsWithRank

a cada um dos seus documentos

252/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

No esquea de atualizar o template

postsList

tamb

<template name="postsList">
<div class="posts">
{{#each postsWithRank}}
{{> postItem}}
{{/each}}
{{#if nextPath}}
<a class="load-more" href="{{nextPath}}">Load more</a>
{{/if}}
</div>
</template>

client views posts posts

list html

Sejabom,Rebobine
O Meteor

um dos web frameworks mais progressistas e inovadores por a

Mas um

de seus utilitrios parece um retrocesso aos dias dos VCRs e gravadores em v deo

cassete

rewind() .

a funo

Sempre que voc

usa um cursor com

forEach() , map()

ou

fetch() , voc

precisar rebobinar o cursor depois antes que ele esteja pronto para ser utilizado de

novo

E em alguns casos

melhor estar do lado seguro e

preventivamente ao inv

rewind()

o cursor

s de arriscar um erro

Juntandotudo

s podemos agora por tudo junto ao utilizar a callback do templete

administrador do

post_item.js

http://pt.discovermeteor.com/pdf

para a nossa l

gica de animao

rendered

do

253/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Template.postItem.helpers({
//...
});
Template.postItem.rendered = function(){
// animate post from previous position to new position
var instance = this;
var rank = instance.data._rank;
var $this = $(this.firstNode);
var postHeight = 80;
var newPosition = rank * postHeight;

// if element has a currentPosition (i.e. it's not the first ever render)
if (typeof(instance.currentPosition) !== 'undefined') {
var previousPosition = instance.currentPosition;
// calculate difference between old position and new position and send e
lement there
var delta = previousPosition - newPosition;
$this.css("top", delta + "px");
}

};

// let it draw in the old position, then..


Meteor.defer(function() {
instance.currentPosition = newPosition;
// bring element back to its new original position
$this.css("top", "0px");
});

Template.postItem.events({
//...
});

/ _

client views posts post

item js

Commit141

Added post reordering animation

Ver no GitHub

Lanar Instncia

No deve ser muito dif cil acompanhar se voc

http://pt.discovermeteor.com/pdf

usar nosso diagrama pr

vio como refer

ncia

254/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Note que j que n

na callback

currentPosition

s configuramos a propriedade

na instncia do template

defer , isto significa que esta propriedade no existir na primeira renderizao

do fragmento de template

Mas isto no

um problema j que n

em animar a primeira renderizao mesmo

Agora abra seu site e comece a votar

Voc

s no estamos interessados

deve agora ver os artigos gentilmente se moverem

para cima e para baixo com uma graa de bal

AnimandoNovosArtigos

Nossos artigos agora esto se reordenando apropriadamente

uma animao

topo da nossa lista

Isto

2.

ainda

s no temos realmente

s de simplesmente ter novos artigos pipocando no

vamos fade them in

Ao inv

na verdade mais complicado do que parece

Meteor

1.

new post

mas n

disparada em dois casos separados

Quando um novo template

O problema

rendered

que a callback

do

inserido no DOM

Toda vez que a informao subjacente de um template muda

Apenas o caso

deve ser animado

a no ser que voc

queria que a interface do usurio se

ilumine como uma rvore de natal toda vez que a informao mudar

Vamos assegurar que n

s apenas animemos os artigos quando eles de fato so novos

quando eles so re renderizados porque a informao mudou

presena de uma varivel de instncia

),

renderizao

bloco

else :

ento n

http://pt.discovermeteor.com/pdf

a qual

e no

s j estamos testando pela

apenas definida ap

s apenas precisamos voltar a nossa callback

s a primeira

rendered

e adicionar um

255/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Template.postItem.helpers({
//...
});
Template.postItem.rendered = function(){
// anima o artigo da posio prvia para a nova posio
var instance = this;
var rank = instance.data._rank;
var $this = $(this.firstNode);
var postHeight = 80;
var newPosition = rank * postHeight;

// se o elemento tem uma currentPosition (vulgo no a primeira renderiza


o)
if (typeof(instance.currentPosition) !== 'undefined') {
var previousPosition = instance.currentPosition;
// calcule a diferena entra a posio antiga e a nova posio e envie o
elemento para l
var delta = previousPosition - newPosition;
$this.css("top", delta + "px");
} else {
// a primeira renderizao, ento esconda o elemento
$this.addClass("invisible");
}

};

// deixe desenhar na posio antiga, ento..


Meteor.defer(function() {
instance.currentPosition = newPosition;
// traga elemento de volta a sua nova posio original
$this.css("top", "0px").removeClass("invisible");
});

Template.postItem.events({
//...
});

/ _

client views posts post

item js

Commit142
Fade items in when they are drawn

Ver no GitHub

http://pt.discovermeteor.com/pdf

Lanar Instncia

256/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

removeClass("invisible")

Note que a

para cada renderizao

presente no elemento

que n

s adicionamos na funo

defer()

.invisible

Mas apenas far alguma coisa se a classe

rodar

estiver

o que ser verdadeiro apenas a primeira vez que for renderizado

CSS&JavaScript
Voc

top .

pode ter notado que n

disparar a animao ao inv

como n

s fizemos para

.invisible

s estamos usando uma classe CSS

s de animar a propriedade CSS

Isto

porque para

opacity

para

diretamente

top , ns precisavamos animar a

propriedade para um valor espec fico que dependia da informao da instncia

Por outro lado

aqui n

s apenas queremos mostrar e esconder um elemento

.
,

independente de sua informao

seu JavaScript o mximo poss vel

classe aqui

uma boa id

ia manter sua CSS longe do

s apenas adicionaremos e removeremos a

e especificaremos os detalhes da animao na nossa stylesheet

J que

s devemos finalmente ter o comportamento de animao que n

aplicativo e experimente

.post.invisible
functions

E agora voc

para ver se voc

tamb

m pode brincar com as classes

consegue desenvolver outras transi

s quer amos

.
es

Rode seu

.post

Dica

CSS easing

um bom lugar para comear

http://pt.discovermeteor.com/pdf

257/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

VocabulrioMeteor

Neste livro voc

14.5

SIDEBAR

ir encontrar algumas palavras que podem ser novas

ou pelo menos usadas

de uma forma nova no contexto de Meteor

Vamos usar este cap tulo para as definir

Cliente
Quando falamos do Cliente

utilizadores

estamos a referir c

digo a correr no navegador web dos

seja isso um navegador tradicional como o Firefox ou o Safari

ou algo to

complexo como uma UIWebView numa aplicao de iPhone nativa

Coleo

Uma Coleo Meteor

cliente e servidor

a entidade gestora de dados que automaticamente sincroniza entre

As Cole

es t

m um nome

existem tanto no cliente como no servidor

como por exemplo

posts , e normalmente

Apesar de terem comportamentos diferentes

elas

m uma API comum baseada na de Mongo

Computao
Uma computao

um bloco de c

que ela depende muda

Sesso

digo que corre cada vez que uma fonte de dados reativa de

Se tiver uma fonte de dados reativa

e quiser responder lhe reativamente

por exemplo

uma varivel de

vai ser necessrio estabelecer uma computao

para ela

Cursor
Um cursor

cursor no

o resultado de correr uma pesquisa numa coleo de Mongo

simplesmente uma lista de resultados

No cliente

um

mas um objecto reactivo que pode ser

observado enquanto objetos na coleo relevante so adicionados

removidos ou atualizados

DDP
DDP

o Protocolo de Dados Distribu dos

baixo n vel utilizado para sincronizar cole

http://pt.discovermeteor.com/pdf

Distributed Data Protocol

es e fazer chamadas a M

de Meteor

todos

o protocolo de

O DDP foi

258/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

desenhado com a inteno de ser um protocolo gen

rico

que substitui o HTTP para

aplica

es de tempo real com grandes quantidades de dados

Deps
Deps

o sistema de reatividade do Meteor

Deps

usado internamente para manter o HTML

sincronizado com o modelo de dados subjacente

Documento

O Mongo

das cole

podem

uma fonte de dados baseada em documentos

es so chamados

no entanto

documentos

conter fun

es

nesse sentido os objetos que saem

Estes so objetos JavaScript simples

com uma

nica propriedade especial

utilizado pelo Meteor para gerir as suas propriedades atrav

que no

_id , que

s do DDP

Ajudante
Quando um template precisa de renderizar algo mais complexo que uma propriedade de um

documento ele pode chamar um ajudante

uma funo que

utilizada para ajudar no

processo de renderizar

CompensaodeLatncia
uma t

cnica utilizada para permitir simular chamadas a M

todos no cliente

para evitar

demoras enquanto se espera que o servidor responda

Mtodo

Um M

todo de Meteor

uma chamada a uma funo remota do cliente para o servidor

alguma l

Lat

gica especial para gerir altera

com

es nas cole

es e suportar Compensao de

ncia

MiniMongo

A coleo no lado do cliente

semelhante de Mongo

http://pt.discovermeteor.com/pdf

uma base de dados em mem

ria que disponibiliza uma API

A biblioteca que suporta este comportamento

chamada

259/261

1/8/2015

MiniMongo

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman
para indicar que

completamente em mem

uma verso mais pequena do Mongo que corre

.
ria

Pacote
Um pacote Meteor pode consistir de

1.
C

digo JavaScript para correr no servidor

2.
C

3.
4.

digo JavaScript para correr no cliente

Instru

es sobre como processar recursos

).

como SASS para CSS

Recursos para serem processados

Um pacote

como uma biblioteca com super poderes

grande de pacotes base

O Meteor vem com um conjunto

Existe ainda o projecto Atmosphere

de terceiros criado pela comunidade

que

uma coleo de pacotes

Publicao

Uma publicao

um conjunto de dados com um nome e que

utilizador que o subscreve

customizado por cada

As publica

es so definidas no servidor

Servidor
O servidor Meteor

. .

um servidor HTTP e DDP que corre em node js

bibliotecas de Meteor

servidor Meteor

e do c

Consiste de todas as

digo JavaScript de servidor escrito por si

este liga se a uma base de dados Mongo

).

Quando voc

que tamb

inicia um

iniciada

automaticamente quando em desenvolvimento

Sesso
A Sesso em Meteor

uma fonte de dados reativa no cliente que

para manter o estado em que o utilizador est

usada pela sua aplicao

Subscrio
http://pt.discovermeteor.com/pdf

260/261

1/8/2015

Discover Meteor Building Real-Time JavaScript Web Apps Sacha Greif & Tom Coleman

Uma subscrio

uma ligao a uma publicao para um cliente espec fico

A subscrio

digo que corre no navegador que comunica com uma publicao no servidor e mant

dados sincronizados

m os

Template
Um template

Handlebars

um m

todo de gerar HTML em JavaScript

um sistema de templates sem l

gica

Por omisso

Meteor suporta

apesar de haver planos para suportar outros

no futuro

ContextodeDadosdoTemplate

Quando um template

renderizado

espec ficos para a renderizao em questo

JavaScript objects

POJOs

),

- -

Tipicamente tais objectos so plain old

normalmente documentos de uma coleo

ser mais complexos e ter fun

http://pt.discovermeteor.com/pdf

este baseia se num objecto JavaScript que fornece dados

apesar de poderem

.
es

261/261

You might also like