lib/counter/integration/counters.rb in counterwise-0.1.1 vs lib/counter/integration/counters.rb in counterwise-0.1.2

- old
+ new

@@ -53,37 +53,69 @@ @counter_configs ||= [] counter_definitions = Array.wrap(counter_definitions) counter_definitions.each do |definition_class| definition = definition_class.instance - association_name = definition.association_name + definition.model = self - # Find the association on this model - association_reflection = reflect_on_association(association_name) - # Find the association classes - association_class = association_reflection.class_name.constantize - inverse_association = association_reflection.inverse_of + scope :with_counter_data_from, ->(*counter_classes) { + subqueries = ["#{table_name}.*"] + counter_classes.each do |counter_class| + sql = Counter::Value.select("value") + .where("parent_id = #{table_name}.id AND parent_type = '#{name}' AND name = '#{counter_class.instance.record_name}'").to_sql + subqueries << "(#{sql}) AS #{counter_class.instance.name}_data" + end + select(subqueries) + } - raise Counter::Error.new("#{association_name} must have an inverse_of specified to be used in #{definition_class.name}") if inverse_association.nil? + # Expects a hash of counter classes and directions, like so: + # order_by_counter ProductCounter => :desc, PremiumProductCounter => :asc + scope :order_by_counter, ->(order_hash) { + counter_classes = order_hash.keys.select { |counter_class| + counter_class.is_a?(Class) && + counter_class.ancestors.include?(Counter::Definition) + } + order_params = {} + order_hash.map do |counter_class, direction| + if counter_class.is_a?(String) || counter_class.is_a?(Symbol) + order_params[counter_class] = direction + elsif counter_class.ancestors.include?(Counter::Definition) + order_params["#{counter_class.instance.name}_data"] = direction + end + end + with_counter_data_from(*counter_classes).order(order_params) + } - # Add the after_commit hook to the association's class - association_class.include Counter::Countable - # association_class.include Counter::Changed + scope :with_counters, -> { includes(:counters) } - # Update the definition with the association class and inverse association - # gathered from the reflection - definition.model = self - definition.inverse_association = inverse_association.name - definition.countable_model = association_class - define_method definition.method_name do counters.find_or_create_counter!(definition) end - # Provide the Countable class with details about where it's counted + @counter_configs << definition unless @counter_configs.include?(definition) - @counter_configs << definition - association_class.add_counted_by definition + association_name = definition.association_name + if association_name.present? + # Find the association on this model + association_reflection = reflect_on_association(association_name) + raise Counter::Error.new("#{association_name} does not exist #{self.name}") if association_reflection.nil? + + # Find the association classes + association_class = association_reflection.class_name.constantize + inverse_association = association_reflection.inverse_of + raise Counter::Error.new("#{association_name} must have an inverse_of specified to be used in #{definition_class.name}") if inverse_association.nil? + + # Add the after_commit hook to the association's class + association_class.include Counter::Countable + + # Update the definition with the association class and inverse association + # gathered from the reflection + definition.inverse_association = inverse_association.name + definition.countable_model = association_class + + # Provide the Countable class with details about where it's counted + association_class.add_counted_by definition + end end end # Returns a list of Counter::Definitions def counter_configs