From e94358798d85b355865ce21a04cdead90fa6f7ed Mon Sep 17 00:00:00 2001 From: Toby Lawrence Date: Tue, 23 Aug 2016 15:13:16 -0400 Subject: [PATCH] Try plucking instead of mapping. Use pluck instead of map for upvoted/downvoted IDs. Mapping involves doing the projection locally, whereas plucking will ask MongoDB to do the projection for us. This is the difference between sending the whole document back and sending back the ObjectId itself. Multipled against hundreds or thousands of documents, mapping can really add up, so plucking should really help these 99%'ile cases. --- models/user.rb | 4 ++-- spec/api/user_spec.rb | 25 ++++++++++++++++++++++++- spec/models/user_spec.rb | 22 ++++++++++++++++++++++ spec/spec_helper.rb | 11 +++++++++++ 4 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 spec/models/user_spec.rb diff --git a/models/user.rb b/models/user.rb index 05fd142..48443fa 100644 --- a/models/user.rb +++ b/models/user.rb @@ -111,11 +111,11 @@ class User end def upvoted_ids - Content.up_voted_by(self).map(&:id) + Content.up_voted_by(self).pluck(:_id) end def downvoted_ids - Content.down_voted_by(self).map(&:id) + Content.down_voted_by(self).pluck(:_id) end def followers diff --git a/spec/api/user_spec.rb b/spec/api/user_spec.rb index 1346d05..e43bcb9 100644 --- a/spec/api/user_spec.rb +++ b/spec/api/user_spec.rb @@ -42,10 +42,15 @@ describe "app" do end it "returns error if new information has conflict with other users" do put "/api/v1/users/1", username: "user2" - last_response.status.should == 400 + last_response.status.should == 400 end end + describe "GET /api/v1/users/:user_id" do + let(:author) { User.find_by(external_id: "1") } + let(:reader) { User.find_by(external_id: "2") } + let(:thread) { make_standalone_thread(author) } + it "returns user information" do get "/api/v1/users/1" last_response.status.should == 200 @@ -54,10 +59,28 @@ describe "app" do res["external_id"].should == user1.external_id res["username"].should == user1.username end + it "returns 404 if user does not exist" do get "/api/v1/users/3" last_response.status.should == 404 end + + it "returns no threads when user hasn't voted" do + get "/api/v1/users/1", complete: "true" + last_response.status.should == 200 + res = parse(last_response.body) + res["upvoted_ids"].should == [] + end + + it "returns threads when user votes" do + reader.vote(thread, :up) + + get "/api/v1/users/2", complete: "true" + last_response.status.should == 200 + res = parse(last_response.body) + res["upvoted_ids"].should == [thread.id.to_s] + end + describe "Returns threads_count and comments_count" do before(:each) { setup_10_threads } diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb new file mode 100644 index 0000000..3077bdc --- /dev/null +++ b/spec/models/user_spec.rb @@ -0,0 +1,22 @@ +require 'spec_helper' +require 'unicode_shared_examples' + +describe User do + let(:author) { create_test_user(666) } + let(:reader) { create_test_user(667) } + let(:thread) { make_standalone_thread(author) } + + before(:each) do + [Comment, CommentThread, User].each(&:delete_all).each(&:remove_indexes).each(&:create_indexes) + end + + it "should have no votes if it never voted" do + reader.upvoted_ids.should == [] + end + + it "should have one vote if it voted once" do + reader.upvoted_ids.should == [] + reader.vote(thread, :up) + reader.upvoted_ids.should == [thread._id] + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index cab9804..77eab93 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -342,6 +342,17 @@ def make_comment(author, parent, text) comment end +def make_standalone_thread(author) + make_thread( + author, + "standalone thread 0", + DFLT_COURSE_ID, + "pdq", + :discussion, + :standalone + ) +end + # add standalone threads and comments to the @threads and @comments hashes # using the namespace "standalone t#{index}" for threads and "standalone t#{index} c#{i}" for comments # takes an index param if used within an iterator, otherwise will namespace using 0 for thread index