get rid of the commentable collection in the database

This commit is contained in:
Rocky Duan 2012-07-18 12:53:32 -04:00
Родитель 323f75139b
Коммит 0fe7d2b7c9
6 изменённых файлов: 75 добавлений и 63 удалений

22
app.rb
Просмотреть файл

@ -19,19 +19,17 @@ Mongoid.logger.level = Logger::INFO
Dir[File.dirname(__FILE__) + '/models/*.rb'].each {|file| require file}
delete '/api/v1/:commentable_type/:commentable_id/threads' do |commentable_type, commentable_id|
commentable = Commentable.find_or_initialize_by(commentable_type: commentable_type, commentable_id: commentable_id)
commentable.destroy
commentable.to_hash.to_json
delete '/api/v1/:commentable_id/threads' do |commentable_id|
Commentable.find(commentable_id).comment_threads.destroy_all
{}.to_json
end
get '/api/v1/:commentable_type/:commentable_id/threads' do |commentable_type, commentable_id|
commentable = Commentable.find_or_create_by(commentable_type: commentable_type, commentable_id: commentable_id)
commentable.comment_threads.map{|t| t.to_hash(recursive: params["recursive"])}.to_json
get '/api/v1/:commentable_id/threads' do |commentable_id|
Commentable.find(commentable_id).comment_threads.map{|t| t.to_hash(recursive: params["recursive"])}.to_json
end
post '/api/v1/:commentable_type/:commentable_id/threads' do |commentable_type, commentable_id|
commentable = Commentable.find_or_create_by(commentable_type: commentable_type, commentable_id: commentable_id)
post '/api/v1/:commentable_id/threads' do |commentable_id|
commentable = Commentable.find(commentable_id)#_or_create_by(commentable_type: commentable_type, commentable_id: commentable_id)
thread = commentable.comment_threads.new(params.slice(*%w[title body course_id]))
thread.author = User.find_or_create_by(external_id: params["user_id"]) if params["user_id"]
thread.save!
@ -120,8 +118,8 @@ post '/api/v1/users/:user_id/subscriptions' do |user_id|
User.find_or_create_by(external_id: params["source_id"])
when "thread"
CommentThread.find(params["source_id"])
else
Commentable.find_or_create_by(commentable_type: params["source_type"], commentable_id: params["source_id"])
when "other"
Commentable.find(params["source_id"])#find_or_create_by(commentable_type: params["source_type"], commentable_id: params["source_id"])
end
user.subscribe(source).to_hash.to_json
end
@ -134,7 +132,7 @@ delete '/api/v1/users/:user_id/subscriptions' do |user_id|
when "thread"
CommentThread.find(params["source_id"])
else
Commentable.find_or_create_by(commentable_type: params["source_type"], commentable_id: params["source_id"])
Commentable.find(params["source_id"])#find_or_create_by(commentable_type: params["source_type"], commentable_id: params["source_id"])
end
user.unsubscribe(source).to_hash.to_json
end

Просмотреть файл

@ -9,13 +9,12 @@ class CommentThread < Content
field :title, type: String
field :body, type: String
field :course_id, type: String, index: true
field :commentable_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
has_many :comments, dependent: :destroy, autosave: true# Use destroy to envoke callback on the top-level comments TODO async
has_many :subscriptions, as: :source
attr_accessible :title, :body, :course_id
attr_accessible :title, :body, :course_id, :commentable_id
validates_presence_of :title
validates_presence_of :body
@ -24,6 +23,14 @@ class CommentThread < Content
after_create :handle_after_create
def commentable
Commentable.find(commentable_id)
end
def subscriptions
Subscription.where(source_id: id.to_s, source_type: self.class.to_s)
end
def subscribers
subscriptions.map(&:subscriber)
end
@ -44,8 +51,8 @@ private
notification = Notification.new(
notification_type: "post_topic",
info: {
commentable_id: commentable.commentable_id,
commentable_type: commentable.commentable_type,
commentable_id: commentable_id,
#commentable_type: commentable.commentable_type,
thread_id: id,
thread_title: title,
},

Просмотреть файл

@ -1,26 +1,24 @@
class Commentable
include Mongoid::Document
field :commentable_type, type: String
field :commentable_id, type: String
attr_accessor :id
alias_attribute :_id, :id
class << self; alias_method :find, :new; end
has_many :comment_threads, dependent: :destroy
has_many :subscriptions, as: :source
def initialize(id)
self.id = id
end
attr_accessible :commentable_type, :commentable_id
def comment_threads
CommentThread.where(commentable_id: id)
end
validates_presence_of :commentable_type
validates_presence_of :commentable_id
validates_uniqueness_of :commentable_id, scope: :commentable_type
index [[:commentable_type, Mongo::ASCENDING], [:commentable_id, Mongo::ASCENDING]]
def subscriptions
Subscription.where(source_id: id.to_s, source_type: self.class.to_s)
end
def subscribers
subscriptions.map(&:subscriber)
end
def to_hash(params={})
as_document.slice(*%w[_id commentable_type commentable_id])
end
end

Просмотреть файл

@ -2,8 +2,9 @@ class Subscription
include Mongoid::Document
include Mongoid::Timestamps
belongs_to :subscriber, class_name: "User", autosave: true, index: true
belongs_to :source, polymorphic: true, autosave: true, index: true
field :subscriber_id, type: String
field :source_id, type: String
field :source_type, type: String
index [[:subscriber_id, Mongo::ASCENDING], [:source_id, Mongo::ASCENDING], [:source_type, Mongo::ASCENDING]]
@ -11,4 +12,12 @@ class Subscription
as_document
end
def subscriber
User.find(subscriber_id)
end
def source
source_type.constantize.find(source_id)
end
end

Просмотреть файл

@ -7,13 +7,19 @@ class User
has_many :comments
has_many :comment_threads, inverse_of: :author
has_many :activities, class_name: "Notification", inverse_of: :actor
has_many :subscriptions_as_source, class_name: "Subscription", as: :source
has_many :subscriptions_as_subscriber, class_name: "Subscription", inverse_of: :subscriber
has_and_belongs_to_many :notifications, inverse_of: :receivers
validates_presence_of :external_id
validates_uniqueness_of :external_id
def subscriptions_as_source
Subscription.where(source_id: id.to_s, source_type: self.class.to_s)
end
def subscriptions_as_subscriber
Subscription.where(subscriber_id: id.to_s)
end
def to_hash(params={})
as_document.slice(*%w[_id external_id])
end

Просмотреть файл

@ -11,17 +11,15 @@ end
def init_without_subscriptions
Comment.delete_all
CommentThread.delete_all
Commentable.delete_all
User.delete_all
Notification.delete_all
Subscription.delete_all
commentable = Commentable.new(commentable_type: "questions", commentable_id: "1")
commentable.save!
commentable = Commentable.new("question_1")
user = User.create!(external_id: "1")
thread = commentable.comment_threads.new(title: "I can't solve this problem", body: "can anyone help me?", course_id: "1")
thread = CommentThread.new(title: "I can't solve this problem", body: "can anyone help me?", course_id: "1", commentable_id: commentable.id)
thread.author = user
thread.save!
@ -42,7 +40,7 @@ def init_without_subscriptions
comment1.author = user
comment1.save!
thread = commentable.comment_threads.new(title: "This problem is wrong", body: "it is unsolvable", course_id: "2")
thread = CommentThread.new(title: "This problem is wrong", body: "it is unsolvable", course_id: "2", commentable_id: commentable.id)
thread.author = user
thread.save!
@ -76,7 +74,6 @@ end
def init_with_subscriptions
Comment.delete_all
CommentThread.delete_all
Commentable.delete_all
User.delete_all
Notification.delete_all
Subscription.delete_all
@ -86,14 +83,11 @@ def init_with_subscriptions
user2.subscribe(user1)
commentable = Commentable.new(commentable_type: "questions", commentable_id: "1")
commentable = Commentable.new("question_1")
user1.subscribe(commentable)
user2.subscribe(commentable)
commentable.save!
commentable = commentable.reload
thread = commentable.comment_threads.new(title: "I can't solve this problem", body: "can anyone help me?", course_id: "1")
thread = CommentThread.new(title: "I can't solve this problem", body: "can anyone help me?", course_id: "1", commentable_id: commentable.id)
thread.author = user1
user2.subscribe(thread)
thread.save!
@ -110,7 +104,7 @@ def init_with_subscriptions
comment2.author = user2
comment2.save!
thread = commentable.comment_threads.new(title: "This problem is wrong", body: "it is unsolvable", course_id: "2")
thread = CommentThread.new(title: "This problem is wrong", body: "it is unsolvable", course_id: "2", commentable_id: commentable.id)
thread.author = user2
thread.save!
end
@ -118,16 +112,16 @@ end
describe "app" do
describe "commentables" do
before(:each) { init_without_subscriptions }
describe "DELETE /api/v1/:commentable_type/:commentable_id/threads" do
it "delete the commentable object and all of its associated comment threads and comments" do
delete '/api/v1/questions/1/threads'
describe "DELETE /api/v1/:commentable_id/threads" do
it "delete all associated threads and comments of a commentable" do
delete '/api/v1/question_1/threads'
last_response.should be_ok
Commentable.count.should == 0
Commentable.find("question_1").comment_threads.count.should == 0
end
end
describe "GET /api/v1/:commentable_type/:commentable_id/threads" do
describe "GET /api/v1/:commentable_id/threads" do
it "get all comment threads associated with a commentable object" do
get "/api/v1/questions/1/threads"
get "/api/v1/question_1/threads"
last_response.should be_ok
threads = Yajl::Parser.parse last_response.body
threads.length.should == 2
@ -135,7 +129,7 @@ describe "app" do
threads.index{|c| c["body"] == "it is unsolvable"}.should_not be_nil
end
it "get all comment threads and comments associated with a commentable object" do
get "/api/v1/questions/1/threads", recursive: true
get "/api/v1/question_1/threads", recursive: true
last_response.should be_ok
threads = Yajl::Parser.parse last_response.body
threads.length.should == 2
@ -154,9 +148,9 @@ describe "app" do
not_for_me["children"].first["body"].should == "not for me neither!"
end
end
describe "POST /api/v1/:commentable_type/:commentable_id/threads" do
describe "POST /api/v1/:commentable_id/threads" do
it "create a new comment thread for the commentable object" do
post '/api/v1/questions/1/threads', title: "Interesting question", body: "cool", course_id: "1", user_id: "1"
post '/api/v1/question_1/threads', title: "Interesting question", body: "cool", course_id: "1", user_id: "1"
last_response.should be_ok
CommentThread.count.should == 3
CommentThread.where(title: "Interesting question").first.should_not be_nil
@ -380,17 +374,17 @@ describe "app" do
end
it "subscribe a commentable" do
user3 = User.find_or_create_by(external_id: "3")
post "/api/v1/users/#{user3.external_id}/subscriptions", source_type: "questions", source_id: "1"
post "/api/v1/users/#{user3.external_id}/subscriptions", source_type: "other", source_id: "question_1"
last_response.should be_ok
Commentable.first.subscribers.length.should == 3
Commentable.first.subscribers.should include user3
Commentable.find("question_1").subscribers.length.should == 3
Commentable.find("question_1").subscribers.should include user3
end
it "unsubscribe a commentable" do
user2 = User.find_or_create_by(external_id: "2")
delete "/api/v1/users/#{user2.external_id}/subscriptions", source_type: "questions", source_id: "1"
delete "/api/v1/users/#{user2.external_id}/subscriptions", source_type: "other", source_id: "question_1"
last_response.should be_ok
Commentable.first.subscribers.length.should == 1
Commentable.first.subscribers.should_not include user2
Commentable.find("question_1").subscribers.length.should == 1
Commentable.find("question_1").subscribers.should_not include user2
end
it "subscribe a comment thread" do
user1 = User.find_or_create_by(external_id: "1")