jam-cloud/ruby/lib/jam_ruby/models/base_search.rb

245 lines
6.3 KiB
Ruby

module JamRuby
class BaseSearch < JsonStore
attr_accessor :page_count, :results, :page_number
ANY_VAL_STR = 'any'
ANY_VAL_INT = -1
VAL_YES = 'yes'
VAL_NO = 'no'
PER_PAGE = 10
PG_SMALLINT_MAX = 32767
KEY_SKILL = 'skill_level'
KEY_GENRES = 'genres'
KEY_INSTRUMENTS = 'instruments'
KEY_GIGS = 'concert_gigs'
KEY_SORT_ORDER = 'sort_order'
KEY_JOINED_WITHIN = 'joined_within_days'
KEY_ACTIVE_WITHIN = 'active_within_days'
SORT_VALS = %W{ latency distance }
SORT_ORDERS = {
SORT_VALS[0] => 'Latency to Me',
SORT_VALS[1] => 'Distance to Me'
}
SKILL_VALS = [ANY_VAL_INT, 1, 2]
SKILL_LEVELS = {
SKILL_VALS[0] => 'Any',
SKILL_VALS[1] => 'Amateur',
SKILL_VALS[2] => 'Pro',
}
JOINED_WITHIN_VALS = [ANY_VAL_INT, 1, 7, 30, 90]
JOINED_WITHIN_LABELS = {
JOINED_WITHIN_VALS[0] => ANY_VAL_STR,
JOINED_WITHIN_VALS[1] => 'Within Last 1 Day',
JOINED_WITHIN_VALS[2] => 'Within Last 7 Day',
JOINED_WITHIN_VALS[3] => 'Within Last 30 Day',
JOINED_WITHIN_VALS[4] => 'Within Last 90 Day',
}
ACTIVE_WITHIN_VALS = [ANY_VAL_INT, 1, 7, 30, 90]
ACTIVE_WITHIN_LABELS = {
ACTIVE_WITHIN_VALS[0] => ANY_VAL_STR,
ACTIVE_WITHIN_VALS[1] => 'Within Last 1 Day',
ACTIVE_WITHIN_VALS[2] => 'Within Last 7 Day',
ACTIVE_WITHIN_VALS[3] => 'Within Last 30 Day',
ACTIVE_WITHIN_VALS[4] => 'Within Last 90 Day',
}
GIG_COUNTS = [ANY_VAL_INT, 0, 1, 2, 3, 4]
GIG_LABELS = {
GIG_COUNTS[0] => 'Any',
GIG_COUNTS[1] => 'under 10',
GIG_COUNTS[2] => '10 to 50',
GIG_COUNTS[3] => '50 to 100',
GIG_COUNTS[4] => 'over 100'
}
INSTRUMENT_PROFICIENCY = {
1 => 'Beginner',
2 => 'Intermediate',
3 => 'Expert',
}
def self.json_schema
{
KEY_SORT_ORDER => self::SORT_VALS[0],
KEY_INSTRUMENTS => [],
KEY_GENRES => [],
KEY_GIGS => self::GIG_COUNTS[0].to_s,
KEY_JOINED_WITHIN => self::JOINED_WITHIN_VALS[0],
}
end
def self.search_filter_meta(jschema=nil, sort_order=nil)
jschema ||= self.json_schema
schema_keys = jschema.keys
sort_order ||= { keys: self::SORT_VALS, map: self::SORT_ORDERS }
multi_keys = jschema.collect { |kk,vv| vv.is_a?(Array) ? kk : nil }.compact
{
per_page: self::PER_PAGE,
filter_keys: {
keys: schema_keys,
multi: multi_keys,
single: schema_keys - multi_keys,
},
sort_order: sort_order
}
end
RESULT_FOLLOW = :follows
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 self.user_search_filter(user)
unless ss = user.send(self.name.demodulize.tableize.singularize)
ss = self.create_search(user)
end
ss
end
def self.search_filter_json(user)
self.user_search_filter(user).json
end
def self.create_search(user)
ms = self.new
ms.user = user
ms.data_blob = self.json_schema
ms.save!
ms
end
def self.search_target_class
end
def self.genre_ids
@@genre_ids ||= Hash[ *Genre.pluck(:id).collect { |v| [ v, v ] }.flatten ]
end
def self.instrument_ids
@@instrument_ids ||= Hash[ *Instrument.pluck(:id).collect { |v| [ v, v ] }.flatten ]
end
def _genres(rel, query_data=json)
gids = query_data[KEY_GENRES]
unless gids.blank?
allgids = self.class.genre_ids
gids = gids.select { |gg| allgids.has_key?(gg) }
unless gids.blank?
gidsql = gids.join("','")
gpsql = "SELECT player_id FROM genre_players WHERE (player_type = '#{self.class.search_target_class.name}' AND genre_id IN ('#{gidsql}'))"
rel = rel.where("#{self.class.search_target_class.table_name}.id IN (#{gpsql})")
end
end
rel
end
def _instruments(rel, query_data=json)
unless (instruments = query_data[KEY_INSTRUMENTS]).blank?
instrids = self.class.instrument_ids
instruments = instruments.select { |ii| instrids.has_key?(ii['instrument_id']) }
unless instruments.blank?
instsql = "SELECT player_id FROM musicians_instruments WHERE (("
instsql += instruments.collect do |inst|
unless MusicianInstrument::PROFICIENCY_RANGE === (proflvl=inst['proficiency_level'].to_i)
proflvl = MusicianInstrument::LEVEL_INTERMEDIATE
end
"instrument_id = '#{inst['instrument_id']}' AND proficiency_level = #{proflvl}"
end.join(") OR (")
instsql += "))"
rel = rel.where("#{self.class.search_target_class.table_name}.id IN (#{instsql})")
end
end
rel
end
def _gigs(rel)
gg = json[KEY_GIGS].to_i
rel = rel.where('concert_count = ?',gg) if 0 <= gg
rel
end
def _skills(rel)
if 0 < (val = json[KEY_SKILL].to_i)
rel = rel.where(['skill_level = ?', val])
end
rel
end
def _joined_within(rel)
#debugger
if 0 < (val = json[KEY_JOINED_WITHIN].to_i)
rel = rel.where("created_at >= ?", val.days.ago.at_beginning_of_day)
end
rel
end
def _sort_order(rel)
end
def do_search(params={})
end
def process_results_page(objs)
end
def search_includes(rel)
rel
end
def search_results_page(filter=nil, page=1, user_ids=nil)
if filter
self.data_blob = filter
self.save
else
filter = self.data_blob
end
rel = do_search(filter, user_ids)
@page_number = [page.to_i, 1].max
rel = rel.paginate(:page => @page_number, :per_page => self.class::PER_PAGE)
rel = self.search_includes(rel)
@page_count = rel.total_pages
process_results_page(rel.all)
end
def reset_filter
self.data_blob = self.class.json_schema
self.save
end
def reset_search_results
reset_filter
search_results_page
end
def search_type
self.class.to_s
end
def is_blank?
self.data_blob == self.class.json_schema
end
def description
end
end
end