Professional Documents
Culture Documents
1 of 24
http://vi.discovermeteor.com/chapters/voting/
1/10/2016 9:37 AM
2 of 24
http://vi.discovermeteor.com/chapters/voting/
upvoters
votes
1/10/2016 9:37 AM
3 of 24
http://vi.discovermeteor.com/chapters/voting/
// Fixture data
if (Posts.find().count() === 0) {
var now = new Date().getTime();
// create two users
});
});
author: sacha.profile.name,
url: 'http://sachagreif.com/introducing-telescope/',
submitted: new Date(now - 7 * 3600 * 1000),
commentsCount: 2,
upvoters: [],
votes: 0
});
Comments.insert({
postId: telescopeId,
userId: tom._id,
author: tom.profile.name,
submitted: new Date(now - 5 * 3600 * 1000),
});
Comments.insert({
postId: telescopeId,
userId: sacha._id,
author: sacha.profile.name,
4 of 24
http://vi.discovermeteor.com/chapters/voting/
});
Posts.insert({
title: 'Meteor',
userId: tom._id,
author: tom.profile.name,
url: 'http://meteor.com',
});
Posts.insert({
author: tom.profile.name,
url: 'http://themeteorbook.com',
submitted: new Date(now - 12 * 3600 * 1000),
commentsCount: 0,
upvoters: [],
votes: 0
});
author: sacha.profile.name,
userId: sacha._id,
url: 'http://google.com/?q=test-' + i,
});
1/10/2016 9:37 AM
5 of 24
http://vi.discovermeteor.com/chapters/voting/
meteor reset
//...
var postWithSameLink = Posts.findOne({url: postAttributes.url});
if (postWithSameLink) {
return {
postExists: true,
_id: postWithSameLink._id
});
_id: postId
//...
1/10/2016 9:37 AM
6 of 24
http://vi.discovermeteor.com/chapters/voting/
<template name="postItem">
<div class="post">
<h3><a href="{{url}}">{{title}}</a><span>{{domain}}</span></h3>
<p>
{{votes}} Votes,
submitted by {{author}},
</p>
</div>
</div>
</template>
1/10/2016 9:37 AM
7 of 24
http://vi.discovermeteor.com/chapters/voting/
//...
Template.postItem.events({
Meteor.call('upvote', this._id);
});
lib/collections/posts.js
1/10/2016 9:37 AM
8 of 24
http://vi.discovermeteor.com/chapters/voting/
//...
Meteor.methods({
post: function(postAttributes) {
},
//...
upvote: function(postId) {
check(this.userId, String);
check(postId, String);
if (_.include(post.upvoters, this.userId))
$inc: {votes: 1}
});
});
//...
$addToSet
1/10/2016 9:37 AM
9 of 24
$inc
http://vi.discovermeteor.com/chapters/voting/
disabled
<template name="postItem">
<div class="post">
//...
</div>
</template>
1/10/2016 9:37 AM
10 of 24
http://vi.discovermeteor.com/chapters/voting/
Template.postItem.helpers({
ownPost: function() {
},
//...
domain: function() {
},
//...
upvotedClass: function() {
} else {
}
});
return 'disabled';
Template.postItem.events({
'click .upvotable': function(e) {
e.preventDefault();
}
});
Meteor.call('upvote', this._id);
.upvote
.upvotable
1/10/2016 9:37 AM
11 of 24
http://vi.discovermeteor.com/chapters/voting/
} else {
}
});
UI.registerHelper
1/10/2016 9:37 AM
12 of 24
http://vi.discovermeteor.com/chapters/voting/
<template name="postItem">
//...
<p>
</p>
//...
</template>
1/10/2016 9:37 AM
13 of 24
http://vi.discovermeteor.com/chapters/voting/
1/10/2016 9:37 AM
14 of 24
http://vi.discovermeteor.com/chapters/voting/
//...
Meteor.methods({
post: function(postAttributes) {
},
//...
upvote: function(postId) {
check(this.userId, String);
check(postId, String);
}, {
$addToSet: {upvoters: this.userId},
$inc: {votes: 1}
});
if (! affected)
});
//...
id
id
1/10/2016 9:37 AM
15 of 24
http://vi.discovermeteor.com/chapters/voting/
postId
deny()
Posts
update
collections/posts.js
update
postList
posts
/new/5
newPosts
/best/5
NewPostsListController
bestPosts
PostsListController
BestPostsListController
/new
/best
1/10/2016 9:37 AM
16 of 24
this.sort
http://vi.discovermeteor.com/chapters/voting/
home
newPosts
BestPostsListController
{submitted: -1}
NewPostsListController
PostsListController
NewPostsListController
1/10/2016 9:37 AM
17 of 24
http://vi.discovermeteor.com/chapters/voting/
//...
PostsListController = RouteController.extend({
template: 'postsList',
increment: 5,
postsLimit: function() {
},
findOptions: function() {
},
subscriptions: function() {
},
posts: function() {
return Posts.find({}, this.findOptions());
},
data: function() {
var hasMore = this.posts().count() === this.postsLimit();
return {
posts: this.posts(),
}
});
};
ready: this.postsSub.ready,
nextPath: hasMore ? this.nextPath() : null
NewPostsController = PostsListController.extend({
sort: {submitted: -1, _id: -1},
nextPath: function() {
return Router.routes.newPosts.path({postsLimit: this.postsLimit()
}
});
BestPostsController = PostsListController.extend({
sort: {votes: -1, submitted: -1, _id: -1},
nextPath: function() {
}
});
1/10/2016 9:37 AM
18 of 24
http://vi.discovermeteor.com/chapters/voting/
Router.route('/', {
name: 'home',
controller: NewPostsController
});
PostsListController
_id
NewPostsController
votes
postsList
nextPath
BestPostsController
Router.route('/:postsLimit?', {
name: 'postsList'
})
1/10/2016 9:37 AM
19 of 24
http://vi.discovermeteor.com/chapters/voting/
<template name="header">
<nav class="navbar navbar-default" role="navigation">
<div class="container-fluid">
<div class="navbar-header">
</button>
</div>
<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 navbar-nav navbar-right">
{{> loginButtons}}
</ul>
</div>
</div>
</nav>
</template>
1/10/2016 9:37 AM
20 of 24
http://vi.discovermeteor.com/chapters/voting/
Router.go('home');
1/10/2016 9:37 AM
21 of 24
<li>
http://vi.discovermeteor.com/chapters/voting/
home
newPosts
activeRouteClass
/new
header.js
1/10/2016 9:37 AM
22 of 24
http://vi.discovermeteor.com/chapters/voting/
<template name="header">
<nav class="navbar navbar-default" role="navigation">
<div class="container-fluid">
<div class="navbar-header">
</button>
</div>
{{#if currentUser}}
<li class="dropdown">
{{> notifications}}
</li>
{{/if}}
</ul>
<ul class="nav navbar-nav navbar-right">
{{> loginButtons}}
</ul>
</div>
</div>
</nav>
</template>
1/10/2016 9:37 AM
23 of 24
http://vi.discovermeteor.com/chapters/voting/
Template.header.helpers({
});
}
});
1/10/2016 9:37 AM
24 of 24
http://vi.discovermeteor.com/chapters/voting/
arguments
any() true
arguments
myString
activeRouteClass
&& myString
pop()
any()
false
true
1/10/2016 9:37 AM