From 4e262de50ab5447eb471c04adcde4cebf2f67cbe Mon Sep 17 00:00:00 2001 From: Jonathan Kolyer Date: Wed, 6 Nov 2013 07:50:34 -0600 Subject: [PATCH] vrfs-774: fixed counters --- ruby/lib/jam_ruby/models/search.rb | 199 ++++++++++++--------- ruby/lib/jam_ruby/models/user.rb | 5 +- web/app/assets/javascripts/findMusician.js | 12 -- web/app/views/api_search/index.rabl | 8 +- web/lib/tasks/sample_data.rake | 10 +- 5 files changed, 127 insertions(+), 107 deletions(-) diff --git a/ruby/lib/jam_ruby/models/search.rb b/ruby/lib/jam_ruby/models/search.rb index fe651c3e6..fa1afc71c 100644 --- a/ruby/lib/jam_ruby/models/search.rb +++ b/ruby/lib/jam_ruby/models/search.rb @@ -2,83 +2,7 @@ module JamRuby # not a active_record model; just a search result class Search attr_accessor :bands, :musicians, :fans, :recordings, :friends, :search_type - attr_accessor :user_mappings, :page_num, :page_count - - PARAM_MUSICIAN = :search_m - LIMIT = 10 - M_PER_PAGE = 4 - - M_ORDER_FOLLOWS = ['Most Followed', :followed] - M_ORDER_PLAYS = ['Most Plays', :plays] - M_ORDER_PLAYING = ['Playing Now', :playing] - M_ORDERINGS = [M_ORDER_FOLLOWS, M_ORDER_PLAYS, M_ORDER_PLAYING] - M_ORDERING_KEYS = M_ORDERINGS.collect { |oo| oo[1] } - - def self.musician_order_param(params) - ordering = params[:orderby] - ordering.blank? ? M_ORDERING_KEYS[0] : M_ORDERING_KEYS.detect { |oo| oo.to_s == ordering } - end - - def self.musician_search(params={}, current_user=nil) - rel = User.where(:musician => true) - unless (instrument = params[:instrument]).blank? - rel = rel.joins("RIGHT JOIN musicians_instruments AS minst ON minst.user_id = users.id") - .where(['minst.instrument_id = ? AND users.id IS NOT NULL', instrument]) - end - - location_distance, location_city = params[:distance], params[:city] - if location_distance && location_city - if geo = MaxMindGeo.where(:city => params[:city]).limit(1).first - citylatlng = [geo.lat, geo.lng] - rel = rel.within(location_distance, :origin => citylatlng) - end - elsif current_user - latlng = [] - if current_user.lat.nil? - if params[:remote_ip] - if geo = MaxMindGeo.ip_lookup(params[:remote_ip]) - latlng = [geo.lat, geo.lng] if geo.lat && geo.lng - end - end - else - latlng = [current_user.lat, current_user.lng] - end - distance = location_distance || 50 - unless latlng.blank? - rel = rel.where(['lat IS NOT NULL AND lng IS NOT NULL']) - .within(distance, :origin => latlng) - end - end - - sel_str = 'users.*' - case ordering = self.musician_order_param(params) - when :plays - when :followed - sel_str = "COUNT(follows) AS search_follow_count, #{sel_str}" - rel = rel.joins("LEFT JOIN users_followers AS follows ON follows.user_id = users.id") - rel = rel.group("users.id") - rel = rel.order("COUNT(follows) DESC, users.created_at DESC") - when :playing - end - - rel = rel.joins("LEFT JOIN friendships AS friends ON friends.user_id = users.id") - sel_str = "#{sel_str}, COUNT(friends) AS search_friend_count" - rel = rel.joins("LEFT JOIN recordings AS records ON records.owner_id = users.id") - sel_str = "#{sel_str}, COUNT(records) AS search_recording_count" - rel = rel.joins("LEFT JOIN music_sessions AS sessions ON sessions.user_id = users.id") - sel_str = "#{sel_str}, COUNT(sessions) AS search_session_count" - - rel = rel.select(sel_str) - perpage = params[:per_page] || M_PER_PAGE - page = [params[:page].to_i, 1].max - rel = rel.paginate(:page => page, :per_page => perpage) - rel.includes([:instruments, :followings, :friends]) - - srch = Search.new - srch.page_num, srch.page_count = page, rel.all.total_pages - srch.musician_results_for_user(rel.all, current_user) - end # performs a site-white search def self.search(query, user_id = nil) @@ -157,51 +81,158 @@ module JamRuby return args end + attr_accessor :user_counters, :page_num, :page_count + + PARAM_MUSICIAN = :search_m + + M_PER_PAGE = 6 + + M_ORDER_FOLLOWS = ['Most Followed', :followed] + M_ORDER_PLAYS = ['Most Plays', :plays] + M_ORDER_PLAYING = ['Playing Now', :playing] + M_ORDERINGS = [M_ORDER_FOLLOWS, M_ORDER_PLAYS, M_ORDER_PLAYING] + M_ORDERING_KEYS = M_ORDERINGS.collect { |oo| oo[1] } + + def self.musician_order_param(params) + ordering = params[:orderby] + ordering.blank? ? M_ORDERING_KEYS[0] : M_ORDERING_KEYS.detect { |oo| oo.to_s == ordering } + end + + def self.musician_search(params={}, current_user=nil) + rel = User.where(:musician => true) + unless (instrument = params[:instrument]).blank? + rel = rel.joins("RIGHT JOIN musicians_instruments AS minst ON minst.user_id = users.id") + .where(['minst.instrument_id = ? AND users.id IS NOT NULL', instrument]) + end + + location_distance, location_city = params[:distance], params[:city] + if location_distance && location_city + if geo = MaxMindGeo.where(:city => params[:city]).limit(1).first + citylatlng = [geo.lat, geo.lng] + rel = rel.within(location_distance, :origin => citylatlng) + end + elsif current_user + latlng = [] + if current_user.lat.nil? + if params[:remote_ip] + if geo = MaxMindGeo.ip_lookup(params[:remote_ip]) + latlng = [geo.lat, geo.lng] if geo.lat && geo.lng + end + end + else + latlng = [current_user.lat, current_user.lng] + end + distance = location_distance || 50 + unless latlng.blank? + rel = rel.where(['lat IS NOT NULL AND lng IS NOT NULL']) + .within(distance, :origin => latlng) + end + end + + sel_str = 'users.*' + case ordering = self.musician_order_param(params) + when :plays + when :followed + sel_str = "COUNT(follows) AS search_follow_count, #{sel_str}" + rel = rel.joins("LEFT JOIN users_followers AS follows ON follows.user_id = users.id") + rel = rel.group("users.id") + rel = rel.order("COUNT(follows) DESC, users.created_at DESC") + when :playing + end + + rel = rel.select(sel_str) + perpage = params[:per_page] || M_PER_PAGE + page = [params[:page].to_i, 1].max + rel = rel.paginate(:page => page, :per_page => perpage) + rel.includes([:instruments, :followings, :friends]) + + srch = Search.new + srch.page_num, srch.page_count = page, rel.all.total_pages + srch.musician_results_for_user(rel.all, current_user) + end + RESULT_FOLLOW = :follows RESULT_LIKE = :likes RESULT_FRIEND = :friends + COUNT_FRIEND = :count_friend + COUNT_FOLLOW = :count_follow + COUNT_RECORD = :count_record + COUNT_SESSION = :count_session + COUNTERS = [COUNT_FRIEND, COUNT_FOLLOW, COUNT_RECORD, COUNT_SESSION] + def musician_results_for_user(results, user) @search_type, @musicians = PARAM_MUSICIAN, results if user - @user_mappings = results.inject({}) { |hh,val| hh[val.id] = []; hh } + @user_counters = results.inject({}) { |hh,val| hh[val.id] = []; hh } mids = "'#{@musicians.map(&:id).join("','")}'" + results.each do |uu| + counters = { } + counters[COUNT_FRIEND] = Friendship.where(:user_id => uu.id).count + counters[COUNT_FOLLOW] = UserFollowing.where(:user_id => uu.id).count + counters[COUNT_RECORD] = Recording.where(:owner_id => uu.id).count + counters[COUNT_SESSION] = MusicSession.where(:user_id => uu.id).count + @user_counters[uu.id] << counters + end rel = User.select("users.id AS uid") rel = rel.joins("LEFT JOIN users_followers AS follows ON follows.follower_id = '#{user.id}'") rel = rel.where(["users.id IN (#{mids}) AND follows.user_id = users.id"]) - rel.all.each { |val| @user_mappings[val.uid] << RESULT_FOLLOW } + rel.all.each { |val| @user_counters[val.uid] << RESULT_FOLLOW } rel = User.select("users.id AS uid") rel = rel.joins("LEFT JOIN users_likers AS likers ON likers.liker_id = '#{user.id}'") rel = rel.where(["users.id IN (#{mids}) AND likers.user_id = users.id"]) - rel.all.each { |val| @user_mappings[val.uid] << RESULT_LIKE } + rel.all.each { |val| @user_counters[val.uid] << RESULT_LIKE } rel = User.select("users.id AS uid") rel = rel.joins("LEFT JOIN friendships AS friends ON friends.friend_id = '#{user.id}'") rel = rel.where(["users.id IN (#{mids}) AND friends.user_id = users.id"]) - rel.all.each { |val| @user_mappings[val.uid] << RESULT_FRIEND } + rel.all.each { |val| @user_counters[val.uid] << RESULT_FRIEND } else - @user_mappings = {} + @user_counters = {} end self end + def _count(musician, key) + if mm = @user_counters[musician.id] + return mm.detect { |ii| ii.is_a?(Hash) }[key] + end + 0 + end + + def follow_count(musician) + _count(musician, COUNT_FOLLOW) + end + + def friend_count(musician) + _count(musician, COUNT_FRIEND) + end + + def record_count(musician) + _count(musician, COUNT_RECORD) + end + + def session_count(musician) + _count(musician, COUNT_SESSION) + end + def is_friend?(musician) - if mm = @user_mappings[musician.id] + if mm = @user_counters[musician.id] return mm.include?(RESULT_FRIEND) end false end def is_follower?(musician) - if mm = @user_mappings[musician.id] + if mm = @user_counters[musician.id] return mm.include?(RESULT_FOLLOW) end false end def is_liker?(musician) - if mm = @user_mappings[musician.id] + if mm = @user_counters[musician.id] return mm.include?(RESULT_LIKE) end false diff --git a/ruby/lib/jam_ruby/models/user.rb b/ruby/lib/jam_ruby/models/user.rb index 3f1f4195b..0e5d386c2 100644 --- a/ruby/lib/jam_ruby/models/user.rb +++ b/ruby/lib/jam_ruby/models/user.rb @@ -18,8 +18,6 @@ module JamRuby # updating_password corresponds to a lost_password attr_accessor :updating_password, :updating_email, :updated_email, :update_email_confirmation_url, :administratively_created, :current_password, :setting_password, :confirm_current_password, :updating_avatar, :updating_progression_field - attr_accessor :search_followings - # authorizations (for facebook, etc -- omniauth) has_many :user_authorizations, :class_name => "JamRuby::UserAuthorization" @@ -981,6 +979,9 @@ module JamRuby end end + attr_accessor :search_counters + + # devise compatibility #def encrypted_password diff --git a/web/app/assets/javascripts/findMusician.js b/web/app/assets/javascripts/findMusician.js index 4e3cc2305..4f3db6d07 100644 --- a/web/app/assets/javascripts/findMusician.js +++ b/web/app/assets/javascripts/findMusician.js @@ -11,18 +11,7 @@ var did_show_musician_page = false; var page_num=1, page_count=0; - function removeSpinner() { - $('') - } - function loadMusicians(queryString) { - addSpinner(); - // squelch nulls and undefines queryString = !!queryString ? queryString : ""; @@ -31,7 +20,6 @@ url: "/api/search.json?" + queryString, async: true, success: afterLoadMusicians, - complete: removeSpinner, error: app.ajaxError }); } diff --git a/web/app/views/api_search/index.rabl b/web/app/views/api_search/index.rabl index e8a1b0f28..5bb803269 100644 --- a/web/app/views/api_search/index.rabl +++ b/web/app/views/api_search/index.rabl @@ -41,10 +41,10 @@ unless @search.musicians.nil? || @search.musicians.size == 0 node :name do |uu| uu.following.name end end - node :follow_count do |musician| musician.search_follow_count.to_i rescue 0 end - node :friend_count do |musician| musician.search_friend_count.to_i rescue 0 end - node :recording_count do |musician| musician.search_recording_count.to_i rescue 0 end - node :session_count do |musician| musician.search_session_count.to_i rescue 0 end + node :follow_count do |musician| @search.follow_count(musician) end + node :friend_count do |musician| @search.friend_count(musician) end + node :recording_count do |musician| @search.record_count(musician) end + node :session_count do |musician| @search.session_count(musician) end } end diff --git a/web/lib/tasks/sample_data.rake b/web/lib/tasks/sample_data.rake index 52a12a1e0..cd8d77f07 100644 --- a/web/lib/tasks/sample_data.rake +++ b/web/lib/tasks/sample_data.rake @@ -116,10 +116,10 @@ end def make_followings users = User.all - users[6..-1].each do |uu| - users[0..5].shuffle.each do |uuu| - uu.followings << uuu - uuu.followings << uu + users.each do |uu| + users[0..rand(users.count)].shuffle.each do |uuu| + uuu.followings << uu unless 0 < UserFollowing.where(:user_id => uu.id, :follower_id => uuu.id).count + uu.followings << uuu unless 0 < UserFollowing.where(:user_id => uuu.id, :follower_id => uu.id).count if rand(3)==0 end end end @@ -131,4 +131,4 @@ def make_friends Friendship.save(uu.id, uuu.id) end end -end \ No newline at end of file +end