Permalink
Fetching contributors…
Cannot retrieve contributors at this time
163 lines (142 sloc) 4.76 KB
module Picky
class Bundle
# TODO Push methods back into the backend, so that we
# can apply more efficient methods tailored for
# each specific backends.
#
# Removes the given id from the indexes.
#
# TODO Simplify (and slow) this again – remove the realtime index.
#
def remove id
# Is it anywhere?
#
str_or_syms = @realtime[id]
return if str_or_syms.blank?
str_or_syms.each do |str_or_sym|
ids = @inverted[str_or_sym]
ids.delete id
if ids.empty?
@inverted.delete str_or_sym
@weights.delete str_or_sym
# Since no element uses this sym anymore, we can delete the similarity for it.
#
# TODO Not really. Since multiple syms can point to the same encoded.
# In essence, we don't know if and when we can remove it.
# (One idea is to add an array of ids and remove from that)
#
@similarity.delete self.similarity_strategy.encode(str_or_sym)
else
@weights[str_or_sym] = self.weight_strategy.weight_for ids.size
# @weights[str_or_sym] = self.weight_strategy.respond_to?(:[]) &&
# self.weight_strategy[str_or_sym] ||
# self.weight_strategy.weight_for(ids.size)
end
end
@realtime.delete id
end
# Returns a reference to the array where the id has been added.
#
# Does not add to realtime if static.
#
# TODO What does static do again?
# TODO Why the realtime index? Is it really necessary?
# Not absolutely. It was for efficient deletion/replacement.
#
def add id, str_or_sym, method: :unshift, static: false, force_update: false
# If static, indexing will be slower, but will use less
# space in the end.
#
if static
ids = @inverted[str_or_sym] ||= empty_array
if force_update
ids.delete id
ids.send method, id
else
# TODO Adding should not change the array if it's already in.
#
if ids.include?(id)
# Do nothing. Not forced, and already in.
else
ids.send method, id
end
end
else
# Use a generalized strategy.
#
str_or_syms = (@realtime[id] ||= []) # (static ? nil : []))
# Inverted.
#
ids = if str_or_syms.include?(str_or_sym)
ids = @inverted[str_or_sym] ||= empty_array
# If updates are forced or if it isn't in there already
# then remove and add to the index.
if force_update || !ids.include?(id)
ids.delete id
ids.send method, id
end
ids
else
# Update the realtime index.
#
str_or_syms << str_or_sym
# TODO Add has_key? to index backends.
# ids = if @inverted.has_key?(str_or_sym)
# @inverted[str_or_sym]
# else
# @inverted[str_or_sym] = empty_array
# end
ids = (@inverted[str_or_sym] ||= empty_array)
ids.send method, id
end
end
# Weights.
#
@weights[str_or_sym] = self.weight_strategy.weight_for ids.size
# Similarity.
#
add_similarity str_or_sym, method: method
# Return reference.
#
ids
end
# Add string/symbol to similarity index.
#
def add_similarity str_or_sym, method: :unshift
if encoded = self.similarity_strategy.encode(str_or_sym)
similars = @similarity[encoded] ||= []
# Not completely correct, as others will also be affected, but meh.
#
similars.delete str_or_sym if similars.include? str_or_sym
similars << str_or_sym
self.similarity_strategy.prioritize similars, str_or_sym
end
end
# Partializes the text and then adds each.
#
def add_partialized id, text, method: :unshift, static: false, force_update: false
partialized text do |partial_text|
add id, partial_text, method: method, static: static, force_update: force_update
end
end
def partialized text, &block
self.partial_strategy.each_partial text, &block
end
# Builds the realtime mapping.
#
# Note: Experimental feature. Might be removed in 5.0.
#
# THINK Maybe load it and just replace the arrays with the corresponding ones.
#
def build_realtime symbol_keys
clear_realtime
@inverted.each_pair do |str_or_sym, ids|
ids.each do |id|
str_or_syms = (@realtime[id] ||= [])
str_or_sym = str_or_sym.to_sym if symbol_keys
@realtime[id] << str_or_sym unless str_or_syms.include? str_or_sym
end
end
end
end
end