mod/follow/set/all/follow/follower_ids.rb
FOLLOWER_IDS_CACHE_KEY = "FOLLOWER_IDS".freeze
card_accessor :followers, type: :list
event :cache_expired_for_type_change, :store, on: :update, changed: %i[type_id name] do
act_card&.schedule_preference_expiration
# FIXME: expire (also?) after save
Card.follow_caches_expired
end
def schedule_preference_expiration
@expire_preferences_scheduled = true
end
def expire_preferences?
@expire_preferences_scheduled
end
event :expire_preferences_cache, :finalize, when: :expire_preferences? do
Card::Rule.clear_preference_cache
end
# follow cache methods on Card class
module ClassMethods
def follow_caches_expired
Card.clear_follower_ids_cache
Card::Rule.clear_preference_cache
end
def follower_ids_cache
Card.cache.read(FOLLOWER_IDS_CACHE_KEY) || {}
end
def write_follower_ids_cache hash
Card.cache.write FOLLOWER_IDS_CACHE_KEY, hash
end
def clear_follower_ids_cache
Card.cache.write FOLLOWER_IDS_CACHE_KEY, nil
end
end
def write_follower_ids_cache user_ids
hash = Card.follower_ids_cache
hash[id] = user_ids
Card.write_follower_ids_cache hash
end
def read_follower_ids_cache
Card.follower_ids_cache[id]
end
def follower_names
followers.map(&:name)
end
def followers
follower_ids.map do |id|
Card.fetch(id)
end
end
def follower_ids
@follower_ids = read_follower_ids_cache || begin
result = direct_follower_ids + indirect_follower_ids
write_follower_ids_cache result
result
end
end
def followers_count
follower_ids.size
end
def indirect_follower_ids
result = ::Set.new
left_card = left
while left_card
result += left_card.direct_follower_ids if left_card.followed_field? self
left_card = left_card.left
end
result
end
# all users (cards) that "directly" follow this card
# "direct" means there is a follow rule that applies explicitly to this card.
# one can also "indirectly" follow cards by following parent cards or other
# cards that nest this one.
def direct_followers
direct_follower_ids.map do |id|
Card.fetch(id)
end
end
def direct_follower_ids &block
ids = ::Set.new
set_names.each do |set_name|
direct_follower_ids_for_set setcard_from_name(set_name), ids, &block
end
ids
end
def setcard_from_name set_name
Card.fetch set_name, new: { type_id: SetID }
end
def direct_follower_ids_for_set set_card, ids
set_card.all_user_ids_with_rule_for(:follow).each do |user_id|
next if ids.include?(user_id) || !(option = follow_rule_option user_id)
yield user_id, set_card, option if block_given?
ids << user_id
end
end
def each_direct_follower_id_with_reason
direct_follower_ids do |user_id, set_card, follow_option|
reason = follow_option.gsub(/[\[\]]/, "")
yield user_id, set_card: set_card, option: reason
end
end