Class: Counter::Definition

Inherits:
Object
  • Object
show all
Includes:
Singleton
Defined in:
lib/counter/definition.rb

Overview

Example usage…

class ProductCounter

include Counter::Definition
# This specifies the association we're counting
count :products
sum :price   # optional
as "my_counter"

end

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#association_nameObject

Attributes set by Counters#counter integration:



14
15
16
# File 'lib/counter/definition.rb', line 14

def association_name
  @association_name
end

#calculated_fromObject

The block to call to calculate the counter



36
37
38
# File 'lib/counter/definition.rb', line 36

def calculated_from
  @calculated_from
end

#column_to_countObject

When using sum, set the column we’re summing



22
23
24
# File 'lib/counter/definition.rb', line 22

def column_to_count
  @column_to_count
end

#conditional=(value) ⇒ Object (writeonly)

Sets the attribute conditional

Parameters:

  • value

    the value to set the attribute conditional to.



25
26
27
# File 'lib/counter/definition.rb', line 25

def conditional=(value)
  @conditional = value
end

#conditionsObject



84
85
86
87
# File 'lib/counter/definition.rb', line 84

def conditions
  @conditions ||= {}
  @conditions
end

#countable_modelObject

Set the thing we’re counting (set by Counters#counter)



18
19
20
# File 'lib/counter/definition.rb', line 18

def countable_model
  @countable_model
end

#counter_hooksObject



94
95
96
97
# File 'lib/counter/definition.rb', line 94

def counter_hooks
  @counter_hooks ||= []
  @counter_hooks
end

#dependent_countersObject



99
100
101
102
# File 'lib/counter/definition.rb', line 99

def dependent_counters
  @dependent_counters ||= []
  @dependent_counters
end

#global_countersObject



89
90
91
92
# File 'lib/counter/definition.rb', line 89

def global_counters
  @global_counters ||= []
  @global_counters
end

#inverse_associationObject

Set the inverse association (i.e., from the products to the user)



20
21
22
# File 'lib/counter/definition.rb', line 20

def inverse_association
  @inverse_association
end

#method_nameObject

Set the name of the counter (used as the method name)



27
28
29
# File 'lib/counter/definition.rb', line 27

def method_name
  @method_name
end

#modelObject

Set the model we’re attached to (set by Counters#counter)



16
17
18
# File 'lib/counter/definition.rb', line 16

def model
  @model
end

#nameObject

Returns the value of attribute name.



28
29
30
# File 'lib/counter/definition.rb', line 28

def name
  @name
end

Class Method Details

.after_change(block) ⇒ Object



163
164
165
# File 'lib/counter/definition.rb', line 163

def self.after_change block
  instance.counter_hooks << block
end

.as(name) ⇒ Object

Set the name of the counter



137
138
139
140
# File 'lib/counter/definition.rb', line 137

def self.as name
  instance.name = name.to_s
  instance.method_name = name.to_s
end

.association_nameObject

Get the name of the association we’re counting



143
144
145
# File 'lib/counter/definition.rb', line 143

def self.association_name
  instance.association_name
end

.calculated_from(*dependent_counters, &block) ⇒ Object



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/counter/definition.rb', line 116

def self.calculated_from *dependent_counters, &block
  instance.dependent_counters = dependent_counters
  instance.calculated_from = block

  dependent_counters.each do |dependent_counter|
    # Install after_change hooks on the dependent counters
    dependent_counter.after_change :update_calculated_counters
    dependent_counter.define_method :update_calculated_counters do |counter, _old_value, _new_value|
      # Fetch all the counters which depend on this one
      calculated_counters = counter.parent.class.counter_configs.select { |c|
        c.dependent_counters.include?(counter.definition.class)
      }

      calculated_counters = calculated_counters.map { |c| counter.parent.counters.find_or_create_counter!(c) }
      # calculate the new values
      calculated_counters.each(&:calculate!)
    end
  end
end

.count(association_name, as: "#{association_name}_counter") ⇒ Object

Set the association we’re counting



105
106
107
108
109
110
# File 'lib/counter/definition.rb', line 105

def self.count association_name, as: "#{association_name}_counter"
  instance.association_name = association_name
  instance.name = as.to_s
  # How the counter can be accessed e.g. counter.products_counter
  instance.method_name = as.to_s
end

.counterObject

Access the counter value for global counters



71
72
73
74
75
# File 'lib/counter/definition.rb', line 71

def self.counter
  raise "Unable to find counter instances via #{name}#counter. Use must use #{instance.model}#find_counter or #{instance.model}##{instance.counter_name}" unless instance.global?

  Counter::Value.find_counter self
end

.find_definition(name) ⇒ Object

for global counter instances to find their definition



66
67
68
# File 'lib/counter/definition.rb', line 66

def self.find_definition name
  Counter::Definition.instance.global_counters.find { |c| c.name == name }
end

.globalObject



112
113
114
# File 'lib/counter/definition.rb', line 112

def self.global
  Counter::Definition.instance.global_counters << instance
end

.on(action, &block) ⇒ Object

Define a conditional filter



153
154
155
156
157
158
159
160
161
# File 'lib/counter/definition.rb', line 153

def self.on action, &block
  instance.conditional = true

  conditions = Counter::Conditions.new
  conditions.instance_eval(&block)

  instance.conditions[action] ||= []
  instance.conditions[action] << conditions
end

.sum(column_name) ⇒ Object

Set the column we’re summing. Leave blank to count the number of items



148
149
150
# File 'lib/counter/definition.rb', line 148

def self.sum column_name
  instance.column_to_count = column_name
end

Instance Method Details

#calculated?Boolean

Is this counter calculated from other counters?

Returns:

  • (Boolean)


54
55
56
# File 'lib/counter/definition.rb', line 54

def calculated?
  !@calculated_from.nil?
end

#conditional?Boolean

Is this counter conditional?

Returns:

  • (Boolean)


49
50
51
# File 'lib/counter/definition.rb', line 49

def conditional?
  @conditional
end

#global?Boolean

Is this a global counter? i.e., not attached to a model

Returns:

  • (Boolean)


44
45
46
# File 'lib/counter/definition.rb', line 44

def global?
  model.nil?
end

#manual?Boolean

Is this a manual counter? Manual counters are not automatically updated from an association or calculated from other counters

Returns:

  • (Boolean)


61
62
63
# File 'lib/counter/definition.rb', line 61

def manual?
  association_name.nil? && !calculated?
end

#record_nameObject

What we record in Counter::Value#name



78
79
80
81
82
# File 'lib/counter/definition.rb', line 78

def record_name
  return name if global?
  return "#{model.name.underscore}-#{association_name}" if association_name.present?
  return "#{model.name.underscore}-#{name}"
end

#sum?Boolean

Is this a counter which sums a column?

Returns:

  • (Boolean)


39
40
41
# File 'lib/counter/definition.rb', line 39

def sum?
  column_to_count.present?
end