module Inter module Actable def self.included(base) base.extend(ClassMethods) base.has_many :interactions, class_name: Inter::Action, as: :interactable end module ClassMethods # def interaction key, value # interactions(key, value).first # end # def interactions key, value # Inter::Action.where(key: key, value: value.to_json, current: true, interactable_type: self.name) # end # def get *options # interaction(key, value).try(:interactable) # end # def get_all key, value # interactions(key, value).map{|int| int.interactable } # end end def method_missing(meth, *args, &block) case meth.to_s when /^is_(.+)!$/ is *process($1) when /^is(nt_.+)!$/ is *process($1) when /^is_(.+)\?$/ is? *process($1) when /^is(nt_.+)\?$/ is? *process($1) when /^was_(.+)\?$/ was? *process($1) when /^was(nt_.+)\?$/ was? *process($1) else super end # if meth.to_s =~ /^is_(.+)\?$/ # check_boolean_interactable($1) # elsif meth.to_s =~ /^is_(.+)!$/ # is $1 # elsif meth.to_s =~ /^isnt_(.+)!$/ # isnt $1 # elsif meth.to_s =~ /^has_(.+)\?$/ # check_length_interactable($1) # elsif meth.to_s =~ /^all_([a-z]+)_counts$/ # count_all_for $1 # elsif meth.to_s =~ /^([a-z_]+)_([a-z]+)_count$/ # count_combined_interaction_relations $1, $2 # elsif meth.to_s =~ /^([a-z_]+)_([a-z]+)_ids$/ # combined_interaction_relation_ids $1, $2 # elsif meth.to_s =~ /^([a-z_]+)_([a-z]+)$/ # combined_interaction_relations $1, $2 # else # super # end end # # Booleans # def is *names [names].flatten.each do |name| set key_for(name), value_for(name) end end def is? *names [names].flatten.each do |name| value = value_for(name) values = value == false ? [value, nil] : [value] return false unless values.include?(get(key_for(name))) end true end # # Complex values # def set key, value interactions.create(key: key, value: value) end def get key interactions.where(key: key, current: true).first.try(:value) end def has? key get(key) != nil end # # History # def was? *names [names].flatten.each do |name| if value_for(name) return false if history(key_for(name)).count == 0 else return false if history(key_for(name)).count > 0 end end true end def history *names [names].flatten.map {|name| interactions.where(key: name)}.flatten end private def process options options.split("_and_") end def value_for name name = name.to_s !(name.starts_with?("not_") || name.starts_with?("is_not_") || name.starts_with?("isnt_") || name.starts_with?("was_not_") || name.starts_with?("wasnt_") || name.starts_with?("nt_")) end def key_for name name = name.to_s name.gsub(/^(is_not_)|(not_)|(isnt_)|(nt_)|(is_)|(was_not_)|(wasnt_)|(was_)/, "") end # private # def check_boolean_interactable key # get(key) == true # end # def check_length_interactable key # interactions.where(key: key).count > 0 # end # def count_all_for relation # relation_ids = send(relation).pluck(:id) # results = Inter::Action.where(interactable_id: relation_ids, current: true.to_s, value: true.to_s).pluck(:key) # results.inject(Hash.new(0)){|h,k| h[k] += 1; h} # end # def count_combined_interaction_relations interactions, relation # combined_interaction_relation_ids(interactions, relation).count # end # def combined_interaction_relations interactions, relation # ids = combined_interaction_relation_ids interactions, relation # klass = relation.singularize.capitalize.constantize # klass.find(ids) # end # def combined_interaction_relation_ids interactions, relation # interactions = interactions.split("_and_") # relation_ids = send(relation).pluck(:id) # interactions.each do |interaction| # value = true # if interaction.starts_with? "not_" # interaction = interaction.gsub("not_", "") # value = false # end # relation_ids &= Inter::Action.search(interaction, value, relation, relation_ids).pluck(:interactable_id).uniq # end # relation_ids # end end end