Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
C
cs_comments_service
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
cs_comments_service
Commits
cb1c0abb
Commit
cb1c0abb
authored
Jul 16, 2012
by
Rocky Duan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feed finally works; not sure if bug caused by custom id or autosave
parent
71fe495b
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
123 additions
and
51 deletions
+123
-51
app.rb
+25
-20
config/application.yml
+3
-0
models/comment.rb
+21
-6
models/comment_thread.rb
+23
-8
models/commentable.rb
+1
-1
models/feed.rb
+2
-2
models/user.rb
+9
-4
spec/app_spec.rb
+39
-10
No files found.
app.rb
View file @
cb1c0abb
...
...
@@ -4,16 +4,20 @@ require 'bundler'
Bundler
.
setup
Bundler
.
require
Dir
[
File
.
dirname
(
__FILE__
)
+
'/models/*.rb'
].
each
{
|
file
|
require
file
}
env_index
=
ARGV
.
index
(
"-e"
)
env_arg
=
ARGV
[
env_index
+
1
]
if
env_index
env
=
env_arg
||
ENV
[
"SINATRA_ENV"
]
||
"development"
module
CommentService
class
<<
self
;
attr_accessor
:config
;
end
end
CommentService
.
config
=
YAML
.
load_file
(
"config/application.yml"
)
Mongoid
.
load!
(
"config/mongoid.yml"
)
Mongoid
.
logger
.
level
=
Logger
::
INFO
config
=
YAML
.
load_file
(
"config/application.yml"
)
Dir
[
File
.
dirname
(
__FILE__
)
+
'/models/*.rb'
].
each
{
|
file
|
require
file
}
# DELETE /api/v1/commentables/:commentable_type/:commentable_id
...
...
@@ -71,7 +75,7 @@ end
post
'/api/v1/commentables/:commentable_type/:commentable_id/comment_threads'
do
|
commentable_type
,
commentable_id
|
commentable
=
Commentable
.
find_or_create_by
(
commentable_type:
commentable_type
,
commentable_id:
commentable_id
)
comment_thread
=
commentable
.
comment_threads
.
new
(
params
.
slice
(
*
%w[title body course_id]
))
comment_thread
.
author
=
User
.
find_or_create_by
(
id:
params
[
"user_id"
])
comment_thread
.
author
=
User
.
find_or_create_by
(
external_
id:
params
[
"user_id"
])
comment_thread
.
save!
comment_thread
.
to_hash
.
to_json
end
...
...
@@ -99,7 +103,7 @@ end
post
'/api/v1/comment_threads/:comment_thread_id/comments'
do
|
comment_thread_id
|
comment_thread
=
CommentThread
.
find
(
comment_thread_id
)
comment
=
comment_thread
.
comments
.
new
(
params
.
slice
(
*
%w[body course_id]
))
comment
.
author
=
User
.
find_or_create_by
(
id:
params
[
"user_id"
])
comment
.
author
=
User
.
find_or_create_by
(
external_
id:
params
[
"user_id"
])
comment
.
save!
comment
.
to_hash
.
to_json
end
...
...
@@ -137,7 +141,7 @@ end
post
'/api/v1/comments/:comment_id'
do
|
comment_id
|
comment
=
Comment
.
find
(
comment_id
)
sub_comment
=
comment
.
children
.
new
(
params
.
slice
(
*
%w[body course_id]
))
sub_comment
.
author
=
User
.
find_or_create_by
(
id:
params
[
"user_id"
])
sub_comment
.
author
=
User
.
find_or_create_by
(
external_
id:
params
[
"user_id"
])
sub_comment
.
save!
sub_comment
.
to_hash
.
to_json
end
...
...
@@ -156,7 +160,7 @@ end
put
'/api/v1/votes/comments/:comment_id/users/:user_id'
do
|
comment_id
,
user_id
|
comment
=
Comment
.
find
(
comment_id
)
user
=
User
.
find_or_create_by
(
id:
user_id
)
user
=
User
.
find_or_create_by
(
external_
id:
user_id
)
user
.
vote
(
comment
,
params
[
"value"
].
intern
)
Comment
.
find
(
comment_id
).
to_hash
.
to_json
end
...
...
@@ -166,7 +170,7 @@ end
delete
'/api/v1/votes/comments/:comment_id/users/:user_id'
do
|
comment_id
,
user_id
|
comment
=
Comment
.
find
(
comment_id
)
user
=
User
.
find_or_create_by
(
id:
user_id
)
user
=
User
.
find_or_create_by
(
external_
id:
user_id
)
user
.
unvote
(
comment
)
Comment
.
find
(
comment_id
).
to_hash
.
to_json
end
...
...
@@ -176,7 +180,7 @@ end
put
'/api/v1/votes/comment_threads/:comment_thread_id/users/:user_id'
do
|
comment_thread_id
,
user_id
|
comment_thread
=
CommentThread
.
find
(
comment_thread_id
)
user
=
User
.
find_or_create_by
(
id:
user_id
)
user
=
User
.
find_or_create_by
(
external_
id:
user_id
)
user
.
vote
(
comment_thread
,
params
[
"value"
].
intern
)
CommentThread
.
find
(
comment_thread_id
).
to_hash
.
to_json
end
...
...
@@ -186,7 +190,7 @@ end
delete
'/api/v1/votes/comment_threads/:comment_thread_id/users/:user_id'
do
|
comment_thread_id
,
user_id
|
comment_thread
=
CommentThread
.
find
(
comment_thread_id
)
user
=
User
.
find_or_create_by
(
id:
user_id
)
user
=
User
.
find_or_create_by
(
external_
id:
user_id
)
user
.
unvote
(
comment_thread
)
CommentThread
.
find
(
comment_thread_id
).
to_hash
.
to_json
end
...
...
@@ -195,16 +199,17 @@ end
# get all subscribed feeds for the user
get
'/api/v1/users/:user_id/feeds'
do
|
user_id
|
user
=
User
.
find_or_create_by
(
id:
user_id
)
user
.
feeds
.
map
(
&
:to_hash
).
to_json
user
=
User
.
find_or_create_by
(
external_id:
user_id
)
puts
user
.
inspect
user
.
subscribed_feeds
.
map
(
&
:to_hash
).
to_json
end
# POST /api/v1/users/:user_id/follow
# follow user
post
'/api/v1/users/:user_id/follow'
do
|
user_id
|
user
=
User
.
find_or_create_by
(
id:
user_id
)
followed_user
=
User
.
find_or_create_by
(
id:
params
[
:user_id
])
user
=
User
.
find_or_create_by
(
external_
id:
user_id
)
followed_user
=
User
.
find_or_create_by
(
external_
id:
params
[
:user_id
])
user
.
follow
(
followed_user
)
user
.
to_hash
.
to_json
end
...
...
@@ -213,8 +218,8 @@ end
# unfollow user
post
'/api/v1/users/:user_id/unfollow'
do
|
user_id
|
user
=
User
.
find_or_create_by
(
id:
user_id
)
followed_user
=
User
.
find_or_create_by
(
id:
params
[
:user_id
])
user
=
User
.
find_or_create_by
(
external_
id:
user_id
)
followed_user
=
User
.
find_or_create_by
(
external_
id:
params
[
:user_id
])
user
.
unfollow
(
followed_user
)
user
.
to_hash
.
to_json
end
...
...
@@ -223,7 +228,7 @@ end
# watch a commentable
post
'/api/v1/users/:user_id/watch/commentable'
do
|
user_id
|
user
=
User
.
find_or_create_by
(
id:
user_id
)
user
=
User
.
find_or_create_by
(
external_
id:
user_id
)
commentable
=
Commentable
.
find_or_create_by
(
commentable_type:
params
[
:commentable_type
],
commentable_id:
parasm
[
:commentable_id
])
user
.
watch_commentable
(
commentable
)
...
...
@@ -234,7 +239,7 @@ end
# unwatch a commentable
post
'/api/v1/users/:user_id/unwatch/commentable'
do
|
user_id
|
user
=
User
.
find_or_create_by
(
id:
user_id
)
user
=
User
.
find_or_create_by
(
external_
id:
user_id
)
commentable
=
Commentable
.
find_or_create_by
(
commentable_type:
params
[
:commentable_type
],
commentable_id:
parasm
[
:commentable_id
])
user
.
unwatch_commentable
(
commentable
)
...
...
@@ -245,7 +250,7 @@ end
# watch a comment thread
post
'/api/v1/users/:user_id/watch/comment_thread'
do
|
user_id
|
user
=
User
.
find_or_create_by
(
id:
user_id
)
user
=
User
.
find_or_create_by
(
external_
id:
user_id
)
comment_thread
=
CommentThread
.
find
(
params
[
:comment_thread_id
])
user
.
watch_comment_thread
(
comment_thread
)
user
.
to_hash
.
to_json
...
...
@@ -255,7 +260,7 @@ end
# unwatch a comment thread
post
'/api/v1/users/:user_id/unwatch/comment_thread'
do
|
user_id
|
user
=
User
.
find_or_create_by
(
id:
user_id
)
user
=
User
.
find_or_create_by
(
external_
id:
user_id
)
comment_thread
=
CommentThread
.
find
(
params
[
:comment_thread_id
])
user
.
unwatch_comment_thread
(
comment_thread
)
user
.
to_hash
.
to_json
...
...
config/application.yml
View file @
cb1c0abb
level_limit
:
3
send_notifications_to_author
:
false
auto_watch_comment_threads
:
true
allow_anonymity
:
true
models/comment.rb
View file @
cb1c0abb
...
...
@@ -10,17 +10,17 @@ class Comment
field
:course_id
,
type:
String
field
:endorsed
,
type:
Boolean
,
default:
false
belongs_to
:author
,
class_name:
"User"
,
index:
true
,
autosave:
true
belongs_to
:comment_thread
,
index:
true
,
autosave:
true
belongs_to
:author
,
class_name:
"User"
,
index:
true
belongs_to
:comment_thread
,
index:
true
attr_accessible
:body
,
:course_id
,
:endorsed
validates_presence_of
:body
validates_presence_of
:course_id
# do we really need this?
#validates_presence_of :author # allow anonymity?
validates_presence_of
:author
if
not
CommentService
.
config
[
"allow_anonymity"
]
before_destroy
:delete_descendants
# TODO async
after_create
:
generate_feeds
after_create
:
handle_after_create
def
self
.
hash_tree
(
nodes
)
nodes
.
map
{
|
node
,
sub_nodes
|
node
.
to_hash
.
merge
(
"children"
=>
hash_tree
(
sub_nodes
).
compact
)}
...
...
@@ -52,7 +52,9 @@ class Comment
end
end
private
def
generate_feeds
if
get_comment_thread
.
watchers
or
(
author
.
followers
if
author
)
feed
=
Feed
.
new
(
feed_type:
"post_reply"
,
info:
{
...
...
@@ -63,10 +65,23 @@ class Comment
)
feed
.
actor
=
author
feed
.
target
=
self
feed
.
subscribers
<<
(
get_comment_thread
.
watchers
+
author
.
followers
).
uniq_by
(
&
:id
).
delete
(
author
)
# doesn't send notification to author
feed
.
subscribers
<<
(
get_comment_thread
.
watchers
+
author
.
followers
).
uniq_by
(
&
:id
)
feed
.
subscribers
.
delete
(
author
)
if
not
CommentService
.
config
[
"send_notifications_to_author"
]
feed
.
save!
end
end
def
auto_watch_comment_thread
if
CommentService
.
config
[
"auto_watch_comment_threads"
]
and
author
author
.
watch_comment_thread
(
get_comment_thread
)
end
end
def
handle_after_create
generate_feeds
#auto_watch_comment_thread
end
handle_asynchronously
:generate_feeds
#handle_asynchronously :handle_after_create
end
models/comment_thread.rb
View file @
cb1c0abb
...
...
@@ -9,23 +9,23 @@ class CommentThread
field
:body
,
type:
String
field
:course_id
,
type:
String
,
index:
true
belongs_to
:author
,
class_name:
"User"
,
inverse_of: :comment_threads
,
index:
true
,
autosave:
true
belongs_to
:commentable
,
index:
true
,
autosave:
true
belongs_to
:author
,
class_name:
"User"
,
inverse_of: :comment_threads
,
index:
true
#
, autosave: true
belongs_to
:commentable
,
index:
true
#
, autosave: true
has_many
:comments
,
dependent: :destroy
# Use destroy to envoke callback on the top-level comments TODO async
has_and_belongs_to_many
:watchers
,
class_name:
"User"
,
inverse_of: :watched_comment_threads
,
autosave:
true
has_and_belongs_to_many
:watchers
,
class_name:
"User"
,
inverse_of: :watched_comment_threads
#
, autosave: true
attr_accessible
:title
,
:body
,
:course_id
validates_presence_of
:title
validates_presence_of
:body
validates_presence_of
:course_id
# do we really need this?
#validates_presence_of :author #allow anonymity?
validates_presence_of
:author
if
not
CommentService
.
config
[
"allow_anonymity"
]
after_create
:
generate_feeds
after_create
:
handle_after_create
def
to_hash
(
params
=
{})
doc
=
as_document
.
slice
(
*
%w[title body course_id _id]
).
merge
(
"user_id"
=>
author
.
id
).
merge
(
"user_id"
=>
(
author
.
id
if
author
)
).
merge
(
"votes"
=>
votes
.
slice
(
*
%w[count up_count down_count point]
))
if
params
[
:recursive
]
doc
=
doc
.
merge
(
"children"
=>
comments
.
map
{
|
c
|
c
.
to_hash
(
recursive:
true
)})
...
...
@@ -33,7 +33,9 @@ class CommentThread
doc
end
private
def
generate_feeds
if
watchers
or
(
author
.
followers
if
author
)
feed
=
Feed
.
new
(
feed_type:
"post_topic"
,
info:
{
...
...
@@ -45,9 +47,22 @@ class CommentThread
)
feed
.
actor
=
author
feed
.
target
=
self
feed
.
subscribers
<<
(
commentable
.
watchers
+
author
.
followers
).
uniq_by
(
&
:id
).
delete
(
author
)
# doesn't send notification to author
feed
.
subscribers
<<
(
commentable
.
watchers
+
(
author
.
followers
if
author
).
to_a
).
uniq_by
(
&
:id
)
feed
.
subscribers
.
delete
(
author
)
if
not
CommentService
.
config
[
"send_notifications_to_author"
]
feed
.
save!
end
end
def
auto_watch_comment_thread
if
CommentService
.
config
[
"auto_watch_comment_threads"
]
and
author
author
.
watch_comment_thread
(
self
)
end
end
def
handle_after_create
generate_feeds
auto_watch_comment_thread
end
handle_asynchronously
:generate_feeds
#handle_asynchronously :handle_after_create
end
models/commentable.rb
View file @
cb1c0abb
...
...
@@ -5,7 +5,7 @@ class Commentable
field
:commentable_id
,
type:
String
has_many
:comment_threads
,
dependent: :destroy
has_and_belongs_to_many
:watchers
,
class_name:
"User"
,
inverse_of: :watched_commentables
,
autosave:
true
has_and_belongs_to_many
:watchers
,
class_name:
"User"
,
inverse_of: :watched_commentables
#
, autosave: true
attr_accessible
:commentable_type
,
:commentable_id
...
...
models/feed.rb
View file @
cb1c0abb
...
...
@@ -5,8 +5,8 @@ class Feed
field
:feed_type
,
type:
String
field
:info
,
type:
Hash
belongs_to
:actor
,
class_name:
"User"
,
inverse_of: :activities
,
index:
true
,
autosave:
true
belongs_to
:target
,
inverse_of: :activities
,
polymorphic:
true
,
autosave:
true
belongs_to
:actor
,
class_name:
"User"
,
inverse_of: :activities
,
index:
true
belongs_to
:target
,
inverse_of: :activities
,
polymorphic:
true
attr_accessible
:feed_type
,
:info
...
...
models/user.rb
View file @
cb1c0abb
...
...
@@ -2,17 +2,20 @@ class User
include
Mongoid
::
Document
include
Mongo
::
Voter
identity
type:
String
field
:external_id
,
type:
String
,
index:
true
has_many
:comments
has_many
:comment_threads
,
inverse_of: :author
has_many
:activities
,
class_name:
"Feed"
,
inverse_of: :actor
has_and_belongs_to_many
:subscribed_feeds
,
class_name:
"Feed"
,
inverse_of: :subscribers
,
autosave:
true
has_and_belongs_to_many
:followers
,
class_name:
"User"
,
inverse_of: :followings
,
autosave:
true
has_and_belongs_to_many
:followings
,
class_name:
"User"
,
inverse_of: :followers
,
autosave:
true
has_and_belongs_to_many
:followers
,
class_name:
"User"
,
inverse_of: :followings
has_and_belongs_to_many
:followings
,
class_name:
"User"
,
inverse_of: :followers
validates_presence_of
:external_id
validates_uniqueness_of
:external_id
def
to_hash
(
params
=
{})
as_document
.
slice
(
*
%w[_id]
)
as_document
.
slice
(
*
%w[_id
external_id
]
)
end
def
follow
(
user
)
...
...
@@ -37,11 +40,13 @@ class User
def watch_
#{
class_single
}
(watching_object)
if not watched_
#{
class_plural
}
.include? watching_object
watched_
#{
class_plural
}
<< watching_object
save!
end
end
def unwatch_
#{
class_single
}
(watching_object)
watched_
#{
class_plural
}
.delete(watching_object)
save!
end
END
end
...
...
spec/app_spec.rb
View file @
cb1c0abb
...
...
@@ -18,7 +18,7 @@ def init_without_feeds
commentable
=
Commentable
.
new
(
commentable_type:
"questions"
,
commentable_id:
"1"
)
commentable
.
save!
user
=
User
.
create!
(
id:
"1"
)
user
=
User
.
create!
(
external_
id:
"1"
)
comment_thread
=
commentable
.
comment_threads
.
new
(
title:
"I can't solve this problem"
,
body:
"can anyone help me?"
,
course_id:
"1"
)
comment_thread
.
author
=
user
...
...
@@ -58,7 +58,7 @@ def init_without_feeds
comment1
.
author
=
user
comment1
.
save!
users
=
(
2
..
10
).
map
{
|
id
|
User
.
find_or_create_by
(
id:
id
.
to_s
)}
users
=
(
2
..
10
).
map
{
|
id
|
User
.
find_or_create_by
(
external_
id:
id
.
to_s
)}
Comment
.
all
.
each
do
|
c
|
user
.
vote
(
c
,
:up
)
# make the first user always vote up for convenience
...
...
@@ -69,6 +69,7 @@ def init_without_feeds
user
.
vote
(
c
,
:up
)
# make the first user always vote up for convenience
users
.
each
{
|
user
|
user
.
vote
(
c
,
[
:up
,
:down
].
sample
)}
end
end
def
init_with_feeds
...
...
@@ -78,10 +79,11 @@ def init_with_feeds
User
.
delete_all
Feed
.
delete_all
user1
=
User
.
create!
(
id:
"1"
)
user2
=
User
.
create!
(
id:
"2"
)
user1
=
User
.
create!
(
external_
id:
"1"
)
user2
=
User
.
create!
(
external_
id:
"2"
)
user1
.
followers
<<
user2
user1
.
save!
commentable
=
Commentable
.
new
(
commentable_type:
"questions"
,
commentable_id:
"1"
)
commentable
.
watchers
<<
[
user1
,
user2
]
...
...
@@ -89,26 +91,34 @@ def init_with_feeds
comment_thread
=
commentable
.
comment_threads
.
new
(
title:
"I can't solve this problem"
,
body:
"can anyone help me?"
,
course_id:
"1"
)
comment_thread
.
author
=
user1
comment_thread
.
watchers
<<
user
1
comment_thread
.
watchers
<<
user
2
comment_thread
.
save!
comment
=
comment_thread
.
comments
.
new
(
body:
"this problem is so easy"
,
course_id:
"1"
)
comment
.
author
=
user
1
comment
.
author
=
user
2
comment
.
save!
comment1
=
comment
.
children
.
new
(
body:
"not for me!"
,
course_id:
"1"
)
comment1
.
author
=
user1
comment1
.
save!
comment2
=
comment1
.
children
.
new
(
body:
"not for me neither!"
,
course_id:
"1"
)
comment2
.
author
=
user
1
comment2
.
author
=
user
2
comment2
.
save!
comment_thread
=
commentable
.
comment_threads
.
new
(
title:
"This problem is wrong"
,
body:
"it is unsolvable"
,
course_id:
"2"
)
comment_thread
.
author
=
user
comment_thread
.
author
=
user
1
comment_thread
.
save!
user1
.
save!
user2
.
save!
pp
Feed
.
all
.
to_a
puts
User
.
first
.
inspect
puts
User
.
first
.
subscribed_feeds
.
inspect
end
describe
"app"
do
=begin
describe "commentables" do
before(:each) { init_without_feeds }
describe "DELETE /api/v1/commentables/:commentable_type/:commentable_id" do
...
...
@@ -156,7 +166,6 @@ describe "app" do
end
end
end
describe "comment threads" do
before(:each) { init_without_feeds }
describe "GET /api/v1/comment_threads/:comment_thread_id" do
...
...
@@ -331,12 +340,31 @@ describe "app" do
end
end
end
=end
describe
"feeds"
do
#
before(:each) { init_with_feeds }
before
(
:each
)
{
init_with_feeds
}
describe
"GET /api/v1/users/:user_id/feeds"
do
it
"get all subscribed feeds for the user"
do
user
=
User
.
where
(
external_id:
"1"
).
first
get
"/api/v1/users/
#{
user
.
external_id
}
/feeds"
last_response
.
should
be_ok
feeds
=
parse
last_response
.
body
pp
feeds
so_easy
=
Comment
.
all
.
select
{
|
c
|
c
.
body
==
"this problem is so easy"
}.
first
not_for_me_neither
=
Comment
.
all
.
select
{
|
c
|
c
.
body
==
"not for me neither!"
}.
first
feed_so_easy
=
feeds
.
select
{
|
f
|
f
[
"feed_type"
]
==
"post_reply"
and
f
[
"info"
][
"comment_id"
]
==
so_easy
.
id
.
to_s
}.
first
feed_so_easy
.
should_not
be_nil
feed_not_for_me_neither
=
feeds
.
select
{
|
f
|
f
[
"feed_type"
]
==
"post_reply"
and
f
[
"info"
][
"comment_id"
]
==
not_for_me_neither
.
id
.
to_s
}.
first
feed_not_for_me_neither
.
should_not
be_nil
feeds
.
each
do
|
feed
|
if
feed
[
"feed_type"
]
==
"post_reply"
feed
[
"info"
][
"comment_body"
]
=
Comment
.
find
(
feed
[
"info"
][
"comment_id"
]).
body
end
end
pp
feeds
end
end
=begin
describe "POST /api/v1/users/:user_id/follow" do
it "follow user" do
...
...
@@ -367,5 +395,6 @@ describe "app" do
end
end
=end
end
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment