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