Class: Counter::Definition
- Inherits:
-
Object
- Object
- Counter::Definition
- 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
-
#association_name ⇒ Object
Attributes set by Counters#counter integration:.
-
#calculated_from ⇒ Object
The block to call to calculate the counter.
-
#column_to_count ⇒ Object
When using sum, set the column we’re summing.
-
#conditional ⇒ Object
writeonly
Sets the attribute conditional.
- #conditions ⇒ Object
-
#countable_model ⇒ Object
Set the thing we’re counting (set by Counters#counter).
- #counter_hooks ⇒ Object
- #dependent_counters ⇒ Object
- #global_counters ⇒ Object
-
#inverse_association ⇒ Object
Set the inverse association (i.e., from the products to the user).
-
#method_name ⇒ Object
Set the name of the counter (used as the method name).
-
#model ⇒ Object
Set the model we’re attached to (set by Counters#counter).
-
#name ⇒ Object
Returns the value of attribute name.
Class Method Summary collapse
- .after_change(block) ⇒ Object
-
.as(name) ⇒ Object
Set the name of the counter.
-
.association_name ⇒ Object
Get the name of the association we’re counting.
- .calculated_from(*dependent_counters, &block) ⇒ Object
-
.count(association_name, as: "#{association_name}_counter") ⇒ Object
Set the association we’re counting.
-
.counter ⇒ Object
Access the counter value for global counters.
-
.find_definition(name) ⇒ Object
for global counter instances to find their definition.
- .global ⇒ Object
-
.on(action, &block) ⇒ Object
Define a conditional filter.
-
.sum(column_name) ⇒ Object
Set the column we’re summing.
Instance Method Summary collapse
-
#calculated? ⇒ Boolean
Is this counter calculated from other counters?.
-
#conditional? ⇒ Boolean
Is this counter conditional?.
-
#global? ⇒ Boolean
Is this a global counter? i.e., not attached to a model.
-
#manual? ⇒ Boolean
Is this a manual counter? Manual counters are not automatically updated from an association or calculated from other counters.
-
#record_name ⇒ Object
What we record in Counter::Value#name.
-
#sum? ⇒ Boolean
Is this a counter which sums a column?.
Instance Attribute Details
#association_name ⇒ Object
Attributes set by Counters#counter integration:
14 15 16 |
# File 'lib/counter/definition.rb', line 14 def association_name @association_name end |
#calculated_from ⇒ Object
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_count ⇒ Object
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
25 26 27 |
# File 'lib/counter/definition.rb', line 25 def conditional=(value) @conditional = value end |
#conditions ⇒ Object
84 85 86 87 |
# File 'lib/counter/definition.rb', line 84 def conditions @conditions ||= {} @conditions end |
#countable_model ⇒ Object
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_hooks ⇒ Object
94 95 96 97 |
# File 'lib/counter/definition.rb', line 94 def counter_hooks @counter_hooks ||= [] @counter_hooks end |
#dependent_counters ⇒ Object
99 100 101 102 |
# File 'lib/counter/definition.rb', line 99 def dependent_counters @dependent_counters ||= [] @dependent_counters end |
#global_counters ⇒ Object
89 90 91 92 |
# File 'lib/counter/definition.rb', line 89 def global_counters @global_counters ||= [] @global_counters end |
#inverse_association ⇒ Object
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_name ⇒ Object
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 |
#model ⇒ Object
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 |
#name ⇒ Object
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_name ⇒ Object
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 |
.counter ⇒ Object
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 |
.global ⇒ Object
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?
54 55 56 |
# File 'lib/counter/definition.rb', line 54 def calculated? !@calculated_from.nil? end |
#conditional? ⇒ Boolean
Is this counter conditional?
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
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
61 62 63 |
# File 'lib/counter/definition.rb', line 61 def manual? association_name.nil? && !calculated? end |
#record_name ⇒ Object
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?
39 40 41 |
# File 'lib/counter/definition.rb', line 39 def sum? column_to_count.present? end |