Class: Metricky::Base

Inherits:
Object show all
Defined in:
lib/metricky/base.rb,
lib/metricky/period.rb,
lib/metricky/ranges.rb

Direct Known Subclasses

ApplicationMetric

Constant Summary collapse

VALID_TYPES =
[:sum, :max, :min, :average, :count].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(params, options = {}) ⇒ Base

Returns a new instance of Base.



8
9
10
11
12
13
14
15
# File 'lib/metricky/base.rb', line 8

def initialize(params, options = {})
  @params = params
  options.each do |k,v|
    self.class.attr_reader k
    self.instance_variable_set("@#{k}", v)
  end
  @query = nil
end

Instance Attribute Details

#paramsObject (readonly)

Returns the value of attribute params.



7
8
9
# File 'lib/metricky/base.rb', line 7

def params
  @params
end

#queryObject (readonly)

Returns the value of attribute query.



7
8
9
# File 'lib/metricky/base.rb', line 7

def query
  @query
end

Class Method Details

.default_range(val = nil) ⇒ Object



6
7
8
# File 'lib/metricky/ranges.rb', line 6

def self.default_range(val = nil)
  self.default_range_key = val
end

.metric_nameObject



51
52
53
# File 'lib/metricky/base.rb', line 51

def self.metric_name
  name.demodulize.sub(/Metric$/, "")
end

.range_priority(key, priority) ⇒ Object

Rewrite the priority of a range thing.

class UserMetric

range_priority '24h', 99

end



15
16
17
# File 'lib/metricky/ranges.rb', line 15

def self.range_priority(key, priority)
  self.ranges[key.to_sym].priority = priority
end

.register_range(key, label: nil, priority: nil, &block) ⇒ Object

Register a range. Priority is used for the select order.

class UserMetric

register_range '15w', label: '15 weeks', priority: 99 do
  15.weeks.ago
end

end

Parameters:

  • key (String)

    The value for the option in the select for the form

  • label (String) (defaults to: nil)

    The text shown on the option in the select for the form

  • priority (Integer) (defaults to: nil)

    What order the resulting collection

  • block (Block/Proc)

    The Ruby-converted value. Usually a DateTime/Date/Time object.

Returns:

  • RangeThing



33
34
35
36
37
# File 'lib/metricky/ranges.rb', line 33

def self.register_range(key, label: nil, priority: nil, &block)
  label ||= key
  priority ||= self.ranges.size
  self.ranges[key.to_sym] = RangeThing.new(label, priority, block)
end

.remove_range(key) ⇒ Object



44
45
46
# File 'lib/metricky/ranges.rb', line 44

def self.remove_range(key)
  self.ranges.delete(key.to_sym)
end

.remove_ranges(*keys) ⇒ Object

Removes the listed ranges from the select



40
41
42
# File 'lib/metricky/ranges.rb', line 40

def self.remove_ranges(*keys)
  keys.each { self.remove_range(key) }
end

.reset_ranges!Object

Remove all ranges



49
50
51
52
# File 'lib/metricky/ranges.rb', line 49

def self.reset_ranges!
  self.ranges = {}
  self.default_range_key = nil
end

Instance Method Details

#chartObject

Must be one of Chartkick charts line_chart, pie_chart, columnchart, bar_chart, areachart, geo_chart, timeline



19
20
21
# File 'lib/metricky/base.rb', line 19

def chart
  :column_chart
end

#chart?Boolean

Returns:

  • (Boolean)


96
97
98
# File 'lib/metricky/base.rb', line 96

def chart?
  results.is_a?(Hash) || results.is_a?(Array)
end

#chart_optionsObject



23
24
25
# File 'lib/metricky/base.rb', line 23

def chart_options
  @chart_options ||= {}
end

#collection_label(range_thing) ⇒ Object



100
101
102
# File 'lib/metricky/ranges.rb', line 100

def collection_label(range_thing)
  "#{range_thing.label}"
end

#columnsObject

Column(s) to perform the calculation on.

:total_in_cents, :department


87
88
89
# File 'lib/metricky/base.rb', line 87

def columns
  'id'
end

#form?Boolean

If you have a static metric that doesn’t need to be queried (e.g. average users age of all users), disable the form

Returns:

  • (Boolean)


92
93
94
# File 'lib/metricky/base.rb', line 92

def form?
  ranges.any?
end

#form_nameObject

Form key



64
65
66
# File 'lib/metricky/base.rb', line 64

def form_name
  "#{uri_key}_metric"
end

#groupObject



104
105
106
# File 'lib/metricky/base.rb', line 104

def group
  false
end

#group?Boolean

Returns:

  • (Boolean)


108
109
110
# File 'lib/metricky/base.rb', line 108

def group?
  group.present?
end

#json?Boolean

Returns:

  • (Boolean)


112
113
114
# File 'lib/metricky/base.rb', line 112

def json?
  false
end

#nameObject



47
48
49
# File 'lib/metricky/base.rb', line 47

def name
  self.class.metric_name
end

#nounObject



32
33
34
35
36
37
38
39
40
# File 'lib/metricky/base.rb', line 32

def noun
  {
      count: "total number of",
      average: "average #{columns} of",
      sum: "total",
      min: "minimum",
      max: "maximum"
  }[type.to_sym]
end

#periodObject

How it’s grouped. Leave nil if no grouping

[:second, :minute, :hour, :day, :week, :month, :quarter, :year, :day_of_week, :hour_of_day, :minute_of_hour, :day_of_month, :month_of_year]



7
8
9
# File 'lib/metricky/period.rb', line 7

def period
  nil
end

#period_columnObject

What column to specify for the period calculation. Normally ‘created_at`



13
14
15
# File 'lib/metricky/period.rb', line 13

def period_column
  'created_at'
end

#rangeObject



104
105
106
# File 'lib/metricky/ranges.rb', line 104

def range
  params.dig(form_name, :range) || default_range_key
end

#range_collectionObject

Used in the HTML form for the metric as the select options



109
110
111
# File 'lib/metricky/ranges.rb', line 109

def range_collection
  ranges.sort_by { |_, range| range.priority }.collect { |key, range_thing| [collection_label(range_thing), key] }
end

#range_columnObject

What column to specify for the range calculation. Normally ‘created_at`



96
97
98
# File 'lib/metricky/ranges.rb', line 96

def range_column
  'created_at'
end

#range_to_valueObject

Lookup the passed range and convert it to a value for our ActiveRecord query



85
86
87
88
89
90
91
92
# File 'lib/metricky/ranges.rb', line 85

def range_to_value
  return nil if range.nil?
  if val = self.ranges[range.to_sym]
    val.value.call
  else
    raise TypeError, "invalid range #{range}. Please define it."
  end
end

#resultsObject

Actual result of the metric



43
44
45
# File 'lib/metricky/base.rb', line 43

def results
  assets
end

#scopeObject

What ActiveRecord class (or scoped class) is being used for the metric

Raises:

  • (NotImplementedError)


74
75
76
# File 'lib/metricky/base.rb', line 74

def scope
  raise NotImplementedError, "please add a scope to your metric."
end

#subtitleObject



59
60
61
# File 'lib/metricky/base.rb', line 59

def subtitle
  "#{noun} #{scope.model_name.human.pluralize}"
end

#titleObject



55
56
57
# File 'lib/metricky/base.rb', line 55

def title
  self.class.metric_name
end

#to_jsonObject



100
101
102
# File 'lib/metricky/base.rb', line 100

def to_json
  results.chart_json
end

#to_partial_pathObject

What partial is rendered.



28
29
30
# File 'lib/metricky/base.rb', line 28

def to_partial_path
  '/metricky/metric'
end

#typeObject

What kind of metric we’re pulling.

Must be one of :sum, :max, :min, :average, :count



81
82
83
# File 'lib/metricky/base.rb', line 81

def type
  :count
end

#uri_keyObject

Param key



69
70
71
# File 'lib/metricky/base.rb', line 69

def uri_key
  self.class.metric_name.tableize
end