module JamRuby class Feed < ActiveRecord::Base belongs_to :recording, class_name: "JamRuby::Recording", inverse_of: :feed, foreign_key: 'recording_id' belongs_to :music_session_history, class_name: "JamRuby::MusicSessionHistory", inverse_of: :feed, foreign_key: 'music_session_id' FIXNUM_MAX = (2**(0.size * 8 -2) -1) SORT_TYPES = ['date', 'plays', 'likes'] TIME_RANGES = { "today" => 1 , "week" => 7, "month" => 30, "all" => 0} TYPE_FILTERS = ['music_session_history', 'recording', 'all'] def self.index(user, params = {}) limit = params[:limit] limit ||= 20 limit = limit.to_i # validate sort sort = params[:sort] sort ||= 'date' raise "not valid sort #{sort}" unless SORT_TYPES.include?(sort) start = params[:start].presence if sort == 'date' start ||= FIXNUM_MAX else start ||= 0 end start = start.to_i time_range = params[:time_range] time_range ||= 'month' raise "not valid time_range #{time_range}" unless TIME_RANGES.has_key?(time_range) type_filter = params[:type] type_filter ||= 'all' raise "not valid type #{type_filter}" unless TYPE_FILTERS.include?(type_filter) target_user = params[:user] target_band = params[:band] #query = Feed.includes([:recording]).includes([:music_session_history]).limit(limit) query = Feed.joins("LEFT OUTER JOIN recordings ON recordings.id = feeds.recording_id") .joins("LEFT OUTER JOIN music_sessions_history ON music_sessions_history.id = feeds.music_session_id") .limit(limit) # handle sort if sort == 'date' query = query.where("feeds.id < #{start}") query = query.order('feeds.id DESC') elsif sort == 'plays' query = query.offset(start) query = query.order("COALESCE(recordings.play_count, music_sessions_history.play_count) DESC ") elsif sort == 'likes' query = query.offset(start) query = query.order("COALESCE(recordings.like_count, music_sessions_history.like_count) DESC ") else raise "sort not implemented: #{sort}" end # handle time range days = TIME_RANGES[time_range] if days > 0 query = query.where("feeds.created_at > NOW() - '#{days} day'::INTERVAL") end # handle type filters if type_filter == 'music_session_history' query = query.where('feeds.music_session_id is not NULL') elsif type_filter == 'recording' query = query.where('feeds.recording_id is not NULL') end if target_user if target_user != user.id require_public_recordings = "claimed_recordings.is_public = TRUE AND" require_public_sessions = "music_sessions_history.fan_access = TRUE AND" end query = query.joins("LEFT OUTER JOIN claimed_recordings ON recordings.id = claimed_recordings.recording_id AND #{require_public_recordings} (claimed_recordings.user_id = '#{target_user}' OR (recordings.band_id IN (SELECT band_id FROM bands_musicians where user_id='#{target_user}')))") query = query.joins("LEFT OUTER JOIN music_sessions_user_history ON music_sessions_history.id = music_sessions_user_history.music_session_id AND #{require_public_sessions} music_sessions_user_history.user_id = '#{target_user}'") query = query.group("feeds.id, feeds.recording_id, feeds.music_session_id, feeds.created_at, feeds.updated_at, recordings.id, music_sessions_history.id") if sort == 'plays' query = query.group("COALESCE(recordings.play_count, music_sessions_history.play_count)") elsif sort == 'likes' query = query.group("COALESCE(recordings.like_count, music_sessions_history.like_count)") end query = query.where('recordings.id is NULL OR claimed_recordings.id IS NOT NULL') query = query.where('music_sessions_history.id is NULL OR music_sessions_user_history.id IS NOT NULL') elsif target_band unless Band.find(target_band).users.include?(user) require_public_recordings = "claimed_recordings.is_public = TRUE AND" require_public_sessions = "music_sessions_history.fan_access = TRUE AND" end query = query.joins("LEFT OUTER JOIN claimed_recordings ON recordings.id = claimed_recordings.recording_id AND #{require_public_recordings} recordings.band_id = '#{target_band}'") query = query.where("music_sessions_history IS NULL OR #{require_public_sessions} music_sessions_history.band_id = '#{target_band}'") query = query.group("feeds.id, feeds.recording_id, feeds.music_session_id, feeds.created_at, feeds.updated_at, recordings.id, music_sessions_history.id") if sort == 'plays' query = query.group("COALESCE(recordings.play_count, music_sessions_history.play_count)") elsif sort == 'likes' query = query.group("COALESCE(recordings.like_count, music_sessions_history.like_count)") end query = query.where('recordings.id is NULL OR claimed_recordings.id IS NOT NULL') #query = query.where('music_sessions_history.id is NULL OR music_sessions_user_history.id IS NOT NULL') else query = query.joins('LEFT OUTER JOIN claimed_recordings ON recordings.id = claimed_recordings.recording_id AND claimed_recordings.is_public = TRUE') query = query.joins("LEFT OUTER JOIN music_sessions_user_history ON music_sessions_history.id = music_sessions_user_history.music_session_id AND music_sessions_history.fan_access = TRUE") query = query.group("feeds.id, feeds.recording_id, feeds.music_session_id, feeds.created_at, feeds.updated_at, recordings.id, music_sessions_history.id") if sort == 'plays' query = query.group("COALESCE(recordings.play_count, music_sessions_history.play_count)") elsif sort == 'likes' query = query.group("COALESCE(recordings.like_count, music_sessions_history.like_count)") end query = query.where('recordings.id is NULL OR claimed_recordings.is_public = TRUE') query = query.where('music_sessions_history.id is NULL OR music_sessions_user_history.id IS NOT NULL') end if params[:hash] if query.length == 0 { query:query, next: nil} elsif query.length < limit { query:query, next: nil} else if sort == 'date' { query:query, next: query.last.id} else { query:query, next: start + limit} end end else if query.length == 0 [query, nil] elsif query.length < limit [query, nil] else if sort == 'date' [query, query.last.id] else [query, start + limit] end end end end end end