Class: Timely::Report

Inherits:
Object
  • Object
show all
Defined in:
lib/timely/report.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Report

This can be overridden to set defaults by calling super(default args)



54
55
56
57
58
59
60
61
62
63
# File 'lib/timely/report.rb', line 54

def initialize(options={})
  options = options.symbolize_keys
  options.reverse_merge! period: :month

  self.period     = options.delete(:period)
  self.length     = options.delete(:length)    || default_length
  self.starts_at  = options.delete(:starts_at) || default_starts_at
  self.ends_at    = options.delete(:ends_at)   if options.has_key?(:ends_at)
  self.options    = options
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object (private)

handle ‘to_#name` methods by looking up a formatter class defined as Timely::Formats::#Timely::Report.namename.camelcase



169
170
171
172
173
174
175
# File 'lib/timely/report.rb', line 169

def method_missing(method, *args, &block)
  if method.to_s =~ /\Ato_(.+)\z/
    to_missing_format $1, args[0]
  else
    super
  end
end

Instance Attribute Details

#lengthObject

Instance Definition ##



51
52
53
# File 'lib/timely/report.rb', line 51

def length
  @length
end

#optionsObject

Instance Definition ##



51
52
53
# File 'lib/timely/report.rb', line 51

def options
  @options
end

#periodObject

Instance Definition ##



51
52
53
# File 'lib/timely/report.rb', line 51

def period
  @period
end

#starts_atObject

Instance Definition ##



51
52
53
# File 'lib/timely/report.rb', line 51

def starts_at
  @starts_at
end

#titleObject

Instance Definition ##



51
52
53
# File 'lib/timely/report.rb', line 51

def title
  @title
end

Class Method Details

.row(title, key = default_key, klass = default_klass, options = {}, &scope) ⇒ Object

Define the report’s rows in a subclass:

row "Stuff", :created_at, :count do
  objects.where type: 'Stuff'
end

When the report is generated, the block is evaluated in the context of the report, so you can use helper methods in the report to filter your scopes. For example, you may want to have a ‘user` attribute on the report and scope each row’s data to that user’s associations.



28
29
30
31
32
33
34
35
36
# File 'lib/timely/report.rb', line 28

def row(title, key=default_key, klass=default_klass, options={}, &scope)
  self._row_args   ||= []
  self._row_scopes ||= []

  klass = symbol_to_row_class klass if klass.is_a?(Symbol)

  self._row_args   << [klass, [title, key, options]]
  self._row_scopes << scope
end

Instance Method Details

#_row_argsObject

Class Definition ##



6
# File 'lib/timely/report.rb', line 6

class_attribute :_row_args, :_row_scopes, instance_writer: false

#cache_keyObject

override the cache key to include information about any objects that affect the scopes passed to each row, e.g. a user



161
162
163
# File 'lib/timely/report.rb', line 161

def cache_key
  title.parameterize
end

#cells(row) ⇒ Object



143
144
145
146
147
# File 'lib/timely/report.rb', line 143

def cells(row)
  (@cells ||= {})[row.title] ||= columns.map do |col|
    Timely::Cell.new(self, col, row)
  end
end

#columnsObject

return an array of column objects representing each time segment



136
137
138
139
140
141
# File 'lib/timely/report.rb', line 136

def columns
  @columns ||= (0..(length-1)).map do |inc|
    args = period == :quarter ? { months: inc*3 } : { periods => inc }
    Timely::Column.new period, starts_at.advance(args)
  end
end

#default_keyObject

Default Row Settings ##



10
# File 'lib/timely/report.rb', line 10

class_attribute :default_key

#ends_atObject

calculate the end time



110
111
112
113
114
115
116
117
118
# File 'lib/timely/report.rb', line 110

def ends_at
  @ends_at ||= begin
    if period == :quarter
      starts_at.advance months: length * 3
    else
      starts_at.advance periods => length
    end
  end
end

#ends_at=(val) ⇒ Object

recalculate the length so that the report includes the given date



100
101
102
103
104
105
106
107
# File 'lib/timely/report.rb', line 100

def ends_at=(val)
  raise Timely::ConfigurationError, "starts_at must be set before setting ends_at" unless starts_at

  duration_in_seconds = val - starts_at
  period_duration = period == :quarter ? 3.months : 1.send(period)

  self.length = (duration_in_seconds.to_f / period_duration).ceil
end

#rawObject

return a hash where each row is a key pointing to an array of cells



150
151
152
# File 'lib/timely/report.rb', line 150

def raw
  @cache ||= Hash[ rows.map { |row| [row, cells(row)] } ]
end

#rowsObject

return an array of row objects after evaluating each row’s scope in the context of self



122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/timely/report.rb', line 122

def rows
  @rows ||= _row_args.map.with_index do |row_args, i|
    klass, args = row_args

    args    = args.dup
    options = args.extract_options!
    proc    = _row_scopes[i]
    scope   = self.instance_eval(&proc)

    klass.new(*args, scope, options)
  end
end

#to_format(formatter_klass, options = {}) ⇒ Object

pass in a custom object that responds to ‘output`



155
156
157
# File 'lib/timely/report.rb', line 155

def to_format(formatter_klass, options={})
  formatter_klass.new(self, options).output
end

#to_sObject



69
70
71
# File 'lib/timely/report.rb', line 69

def to_s
  "#<#{self.class.name} title: \"#{title}\", period: #{period}, starts_at: #{starts_at}, length: #{length}>"
end