1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
/* The PostsDAO must be constructed with a connected database object */
function PostsDAO(db) {
"use strict";
/* If this constructor is called without the "new" operator, "this" points
* to the global object. Log a warning and call it correctly. */
if (false === (this instanceof PostsDAO)) {
console.log('Warning: PostsDAO constructor called without "new" operator');
return new PostsDAO(db);
}
var posts = db.collection("posts");
this.insertEntry = function (title, body, tags, author, callback) {
"use strict";
console.log("inserting blog entry" + title + body);
// fix up the permalink to not include whitespace
var permalink = title.replace( /\s/g, '_' );
permalink = permalink.replace( /\W/g, '' );
// Build a new post
var post = {"title": title,
"author": author,
"body": body,
"permalink":permalink,
"tags": tags,
"comments": [],
"date": new Date()}
// now insert the post
posts.insert(post, function (err, result) {
"use strict";
if (err) return callback(err, null);
console.log("Inserted new post");
callback(err, permalink);
});
}
this.getPosts = function(num, callback) {
"use strict";
posts.find().sort('date', -1).limit(num).toArray(function(err, items) {
"use strict";
if (err) return callback(err, null);
console.log("Found " + items.length + " posts");
callback(err, items);
});
}
this.getPostsByTag = function(tag, num, callback) {
"use strict";
posts.find({ tags : tag }).sort('date', -1).limit(num).toArray(function(err, items) {
"use strict";
if (err) return callback(err, null);
console.log("Found " + items.length + " posts");
callback(err, items);
});
}
this.getPostByPermalink = function(permalink, callback) {
"use strict";
posts.findOne({'permalink': permalink}, function(err, post) {
"use strict";
if (err) return callback(err, null);
// XXX: Look here for final exam to see where we store "num_likes"
// fix up likes values. set to zero if data is not present
if (typeof post.comments === 'undefined') {
post.comments = [];
}
// Each comment document in a post should have a "num_likes" entry, so we have to
// iterate all the comments in the post to make sure that is the case
for (var i = 0; i < post.comments.length; i++) {
if (typeof post.comments[i].num_likes === 'undefined') {
post.comments[i].num_likes = 0;
}
post.comments[i].comment_ordinal = i;
}
callback(err, post);
});
}
this.addComment = function(permalink, name, email, body, callback) {
"use strict";
var comment = {'author': name, 'body': body}
if (email != "") {
comment['email'] = email
}
posts.update({'permalink': permalink}, {'$push': {'comments': comment}}, function(err, numModified) {
"use strict";
if (err) return callback(err, null);
callback(err, numModified);
});
}
this.incrementLikes = function(permalink, comment_ordinal, callback) {
"use strict";
// The "comment_ordinal" argument specifies which comment in the post we are looking at
// Here is an example of how to build a selector with the 'comment_ordinal' variable
// We have to do it this way because a literal object with variables in field names such as:
// { 'comments.' + comment_ordinal + '.author' : 'Frank' } is illegal Javascript.
var selector_example = {};
var comment_ordinal_example = 0;
selector_example['comments.' + comment_ordinal_example + '.author'] = 'Frank';
// Now selector_example = { 'comments.0.author' : 'Frank' } which is a selector for the
// string 'Frank' in the 'author' field of the first element of the 'comments' array (which
// is zero indexed).
// TODO: Final exam question - Increment the number of likes
callback(Error("incrementLikes NYI"), null);
}
}
module.exports.PostsDAO = PostsDAO;
|