module Socialization module RedisStores class Base class << self protected def actors(subject, klass, options = {}) if options[:pluck] Socialization.redis.smembers(generate_forward_key(subject)).inject([]) do |result, element| result << element.match(/\:(\d+)$/)[1] if element.match(/^#{klass}\:/) result end else actors_relation(subject, klass, options) end end def actors_relation(subject, klass, options = {}) ids = actors(subject, klass, :pluck => :id) klass.where("#{klass.table_name}.id IN (?)", ids) end def subjects_relation(actor, klass, options = {}) ids = subjects(actor, klass, :pluck => :id) klass.where("#{klass.table_name}.id IN (?)", ids) end alias victims_relation subjects_relation def subjects(actor, klass, options = {}) if options[:pluck] Socialization.redis.smembers(generate_backward_key(actor)).inject([]) do |result, element| result << element.match(/\:(\d+)$/)[1] if element.match(/^#{klass}\:/) result end else subjects_relation(actor, klass, options) end end alias victims subjects def relation!(actor, subject, options = {}) unless options[:skip_check] || relation?(actor, subject) Socialization.redis.sadd generate_forward_key(subject), generate_redis_value(actor) Socialization.redis.sadd generate_backward_key(actor), generate_redis_value(subject) call_after_create_hooks(actor, subject) true else false end end def unrelation!(actor, subject, options = {}) if options[:skip_check] || relation?(actor, subject) Socialization.redis.srem generate_forward_key(subject), generate_redis_value(actor) Socialization.redis.srem generate_backward_key(actor), generate_redis_value(subject) call_after_destroy_hooks(actor, subject) true else false end end def relation?(actor, subject) Socialization.redis.sismember generate_forward_key(subject), generate_redis_value(actor) end def remove_actor_relations(subject) forward_key = generate_forward_key(subject) actors = Socialization.redis.smembers forward_key Socialization.redis.del forward_key actors.each do |actor| Socialization.redis.srem generate_backward_key(actor), generate_redis_value(subject) end true end def remove_subject_relations(actor) backward_key = generate_backward_key(actor) subjects = Socialization.redis.smembers backward_key Socialization.redis.del backward_key subjects.each do |subject| Socialization.redis.srem generate_forward_key(subject), generate_redis_value(actor) end true end alias remove_victim_relations remove_subject_relations private def key_type_to_type_names(klass) if klass.name.match(/Follow$/) ['follower', 'followable'] elsif klass.name.match(/Like$/) ['liker', 'likeable'] elsif klass.name.match(/Mention$/) ['mentioner', 'mentionable'] else raise Socialization::ArgumentError.new("Can't find matching type for #{klass}.") end end def generate_forward_key(subject) keys = key_type_to_type_names(self) if subject.is_a?(String) "#{keys[0].pluralize.capitalize}:#{subject}" else "#{keys[0].pluralize.capitalize}:#{subject.class}:#{subject.id}" end end def generate_backward_key(actor) keys = key_type_to_type_names(self) if actor.is_a?(String) "#{keys[1].pluralize.capitalize}:#{actor}" else "#{keys[1].pluralize.capitalize}:#{actor.class}:#{actor.id}" end end def generate_redis_value(obj) "#{obj.class.name}:#{obj.id}" end end # class << self end # Base end # RedisStores end # Socialization