tricle 0.2.4 → 0.2.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +14 -2
- data/Rakefile +2 -0
- data/lib/tricle/aggregation.rb +20 -26
- data/lib/tricle/email_helper.rb +126 -12
- data/lib/tricle/mailer.rb +30 -13
- data/lib/tricle/tasks.rb +17 -3
- data/lib/tricle/templates/email.html.erb +9 -9
- data/lib/tricle/time.rb +12 -0
- data/lib/tricle/version.rb +1 -1
- data/spec/app/daily_test_mailer.rb +13 -0
- data/spec/app/daily_test_metric.rb +7 -0
- data/spec/app/monthly_test_mailer.rb +13 -0
- data/spec/app/monthly_test_metric.rb +7 -0
- data/spec/app/random_test_metric.rb +8 -0
- data/spec/app/test_metric_with_no_total.rb +5 -1
- data/spec/fixtures/days.csv +7 -0
- data/spec/fixtures/months.csv +12 -0
- data/spec/unit/aggregation_spec.rb +23 -31
- data/spec/unit/mailer_spec.rb +66 -12
- data/spec/unit/test_metric_spec.rb +3 -3
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4372146161a539991112213326850b05350166b0
|
4
|
+
data.tar.gz: 44e745d968a91ab3e87175efc683c17b987428b7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1e24e644085b382989dd3046a11fb8e5e3b835b08ee49513787ef4c40606ffb99772497db28ee8a3347ae97f5a71740db4bd372807f9a2f691fca4be679f79b6
|
7
|
+
data.tar.gz: 48bd0e13000ea8c0d8bb67c33f4bc32c56aa2bb340f362b5ffaff2ecba4667b2e640fda7157e73d72c85a46e72849fe5c5113d482eb68cafcdcc4affd43dbaca
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Tricle [![Build Status]
|
1
|
+
# Tricle [![Build Status]](https://travis-ci.org/afeld/tricle) [![Code Climate]](https://codeclimate.com/github/afeld/tricle) [![Gem Version]](http://badge.fury.io/rb/tricle)
|
2
2
|
|
3
3
|
Automated metrics reporting via email. It's datastore-agnostic, so you can query SQL, MongoDB, external APIs, etc. to generate the stats you need. See [here](https://github.com/afeld/tricle-afeld) for an example implementation ([live demo](http://tricle.afeld.me/weekly_metrics)). Uses [sparkle](https://github.com/afeld/sparkle) for generating sparklines.
|
4
4
|
|
@@ -141,6 +141,8 @@ class MyMailer < Tricle::Mailer
|
|
141
141
|
# ...
|
142
142
|
)
|
143
143
|
|
144
|
+
self.period = :day # options are :day, :week (default), and :month
|
145
|
+
|
144
146
|
metric MyMetric1
|
145
147
|
metric MyMetric2
|
146
148
|
# ...
|
@@ -247,7 +249,13 @@ end
|
|
247
249
|
To send all Tricle emails, run
|
248
250
|
|
249
251
|
```bash
|
250
|
-
rake tricle:emails:send
|
252
|
+
rake tricle:emails:send # sends all emails
|
253
|
+
```
|
254
|
+
|
255
|
+
or
|
256
|
+
|
257
|
+
```bash
|
258
|
+
rake tricle:emails:daily # sends emails with period = :day
|
251
259
|
```
|
252
260
|
|
253
261
|
To set a speficic time zone, use the `TZ` environment variable (see the list [here](http://en.wikipedia.org/wiki/List_of_tz_database_time_zones)).
|
@@ -274,3 +282,7 @@ TZ=UTC rake tricle:emails:send
|
|
274
282
|
* Heroku Scheduler only supports a maximum of daily tasks, hence needing to use a special task.
|
275
283
|
|
276
284
|
You can trigger the email(s) manually for testing with `heroku run rake tricle:emails:send`.
|
285
|
+
|
286
|
+
[Build Status]: http://img.shields.io/travis/afeld/tricle.svg?style=flat
|
287
|
+
[Gem Version]: http://img.shields.io/gem/v/tricle.svg?style=flat
|
288
|
+
[Code Climate]: http://img.shields.io/codeclimate/github/afeld/tricle.svg?style=flat
|
data/Rakefile
CHANGED
@@ -7,6 +7,8 @@ reset_time
|
|
7
7
|
|
8
8
|
# used for the preview
|
9
9
|
require_relative 'lib/tricle'
|
10
|
+
require_relative 'spec/app/daily_test_mailer.rb'
|
11
|
+
require_relative 'spec/app/monthly_test_mailer.rb'
|
10
12
|
require_relative 'spec/app/group_test_mailer.rb'
|
11
13
|
require_relative 'spec/app/list_test_mailer.rb'
|
12
14
|
require_relative 'spec/app/test_mailer.rb'
|
data/lib/tricle/aggregation.rb
CHANGED
@@ -4,39 +4,33 @@ module Tricle
|
|
4
4
|
module Aggregation
|
5
5
|
extend ActiveSupport::Concern
|
6
6
|
|
7
|
-
def
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
7
|
+
def periods_ago(period, n)
|
8
|
+
case period
|
9
|
+
when :day
|
10
|
+
start_at = self.now.beginning_of_day.ago(n.days)
|
11
|
+
end_at = start_at + 1.day
|
12
|
+
when :week
|
13
|
+
start_at = self.now.beginning_of_week.ago(n.weeks)
|
14
|
+
end_at = start_at + 7.days
|
15
|
+
when :month
|
16
|
+
start_at = self.now.beginning_of_month.advance(months: -n)
|
17
|
+
end_at = start_at.advance(months: 1)
|
18
|
+
end
|
16
19
|
|
17
|
-
def weeks_ago(n)
|
18
|
-
start_at = self.now.beginning_of_week.weeks_ago(n)
|
19
|
-
end_at = start_at + 7.days
|
20
20
|
self.size_for_range(start_at, end_at)
|
21
21
|
end
|
22
22
|
|
23
|
-
def
|
24
|
-
|
23
|
+
def range_values(period, num_durations)
|
24
|
+
range = num_durations.downto(1)
|
25
|
+
range.map do |n|
|
26
|
+
self.periods_ago(period, n)
|
27
|
+
end
|
25
28
|
end
|
26
29
|
|
27
|
-
def
|
28
|
-
|
29
|
-
weeks_range.map{|n| self.weeks_ago(n) }
|
30
|
-
end
|
31
|
-
|
32
|
-
def weeks_average(past_num_weeks)
|
33
|
-
values = self.weekly_values(past_num_weeks)
|
30
|
+
def range_average(period, past_num_durations)
|
31
|
+
values = self.range_values(period, past_num_durations)
|
34
32
|
total = values.reduce(0, :+)
|
35
|
-
total.to_f /
|
36
|
-
end
|
37
|
-
|
38
|
-
def week_average_this_quarter
|
39
|
-
self.weeks_average(13)
|
33
|
+
total.to_f / past_num_durations
|
40
34
|
end
|
41
35
|
end
|
42
36
|
end
|
data/lib/tricle/email_helper.rb
CHANGED
@@ -5,8 +5,48 @@ module Tricle
|
|
5
5
|
module EmailHelper
|
6
6
|
include ActiveSupport::Inflector
|
7
7
|
|
8
|
-
def
|
9
|
-
|
8
|
+
def num_durations
|
9
|
+
case period
|
10
|
+
when :day
|
11
|
+
7 # week
|
12
|
+
when :week
|
13
|
+
13 # quarter
|
14
|
+
when :month
|
15
|
+
12 # year
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def periods_ago(n)
|
20
|
+
case period
|
21
|
+
when :day
|
22
|
+
Date.today.beginning_of_day.ago(n.days)
|
23
|
+
when :week
|
24
|
+
Date.today.beginning_of_week.ago(n.weeks)
|
25
|
+
when :month
|
26
|
+
Date.today.beginning_of_month.advance(months: -n) # for old ActiveSupport
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def end_of_period(beginning)
|
31
|
+
case period
|
32
|
+
when :day
|
33
|
+
beginning.end_of_day
|
34
|
+
when :week
|
35
|
+
beginning.end_of_week
|
36
|
+
when :month
|
37
|
+
beginning.end_of_month
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def add_periods(time, n)
|
42
|
+
case period
|
43
|
+
when :day
|
44
|
+
time.advance(days: n)
|
45
|
+
when :week
|
46
|
+
time.advance(weeks: n)
|
47
|
+
when :month
|
48
|
+
time.advance(months: n)
|
49
|
+
end
|
10
50
|
end
|
11
51
|
|
12
52
|
def format_date(date)
|
@@ -61,7 +101,11 @@ module Tricle
|
|
61
101
|
end
|
62
102
|
|
63
103
|
def dates_range_str(start_at, end_at)
|
64
|
-
|
104
|
+
if end_at
|
105
|
+
"#{ self.format_date(start_at) } - #{ self.format_date(end_at) }"
|
106
|
+
else
|
107
|
+
self.format_date(start_at)
|
108
|
+
end
|
65
109
|
end
|
66
110
|
|
67
111
|
def dates_cell(start_at, end_at)
|
@@ -69,30 +113,100 @@ module Tricle
|
|
69
113
|
%[<div class="date-range">(#{range})</div>].html_safe
|
70
114
|
end
|
71
115
|
|
116
|
+
def single_day_dates_cell(start_at)
|
117
|
+
dates_cell(start_at, nil)
|
118
|
+
end
|
119
|
+
|
72
120
|
def single_week_dates_cell(start_at)
|
73
121
|
dates_cell(start_at, start_at.end_of_week)
|
74
122
|
end
|
75
123
|
|
76
|
-
def
|
77
|
-
|
124
|
+
def single_month_dates_cell(start_at)
|
125
|
+
dates_cell(start_at, start_at.end_of_month)
|
126
|
+
end
|
127
|
+
|
128
|
+
def period
|
129
|
+
self.mailer.period
|
130
|
+
end
|
131
|
+
|
132
|
+
def old_dates_cell
|
133
|
+
dates_cell periods_ago(num_durations), end_of_period(periods_ago(1))
|
134
|
+
end
|
135
|
+
|
136
|
+
def previous_dates_cell
|
137
|
+
dates_cell(
|
138
|
+
periods_ago(2),
|
139
|
+
if period == :day then nil else end_of_period(periods_ago(2)) end
|
140
|
+
)
|
141
|
+
end
|
142
|
+
|
143
|
+
def current_dates_cell
|
144
|
+
dates_cell(
|
145
|
+
periods_ago(1),
|
146
|
+
if period == :day then nil else end_of_period(periods_ago(1)) end
|
147
|
+
)
|
148
|
+
end
|
149
|
+
|
150
|
+
def old_dates_cell_header
|
151
|
+
case period
|
152
|
+
when :day
|
153
|
+
'Weekly average'
|
154
|
+
when :week
|
155
|
+
'Quarterly average'
|
156
|
+
when :month
|
157
|
+
'Yearly average'
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def previous_dates_cell_header
|
162
|
+
case period
|
163
|
+
when :day
|
164
|
+
'2 days ago'
|
165
|
+
when :week
|
166
|
+
'Previous week'
|
167
|
+
when :month
|
168
|
+
'Previous month'
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def current_dates_cell_header
|
173
|
+
case period
|
174
|
+
when :day
|
175
|
+
'Yesterday'
|
176
|
+
when :week
|
177
|
+
'Last week'
|
178
|
+
when :month
|
179
|
+
'Last month'
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def old_data_cell(metric)
|
184
|
+
percent_change_cell metric.periods_ago(period, 1),
|
185
|
+
metric.range_average(period, num_durations),
|
186
|
+
metric.better,
|
187
|
+
metric.unit
|
78
188
|
end
|
79
189
|
|
80
|
-
def
|
81
|
-
|
190
|
+
def previous_data_cell(metric)
|
191
|
+
percent_change_cell metric.periods_ago(period, 1),
|
192
|
+
metric.periods_ago(period, 2),
|
193
|
+
metric.better,
|
194
|
+
metric.unit
|
82
195
|
end
|
83
196
|
|
84
|
-
def
|
85
|
-
|
197
|
+
def current_number(metric)
|
198
|
+
format_number metric.periods_ago(period, 1),
|
199
|
+
metric.unit
|
86
200
|
end
|
87
201
|
|
88
202
|
def list_markup(list)
|
89
|
-
start_at = self.
|
90
|
-
end_at = start_at
|
203
|
+
start_at = self.periods_ago(1).to_time
|
204
|
+
end_at = add_periods(start_at, 1)
|
91
205
|
list.items_markup(start_at, end_at).html_safe
|
92
206
|
end
|
93
207
|
|
94
208
|
def sparkline(metric)
|
95
|
-
values = metric.
|
209
|
+
values = metric.range_values(period, num_durations)
|
96
210
|
attachment_url = "https://sparklines.herokuapp.com/api/v1.png?values=#{values.join(',')}"
|
97
211
|
image_tag(attachment_url, alt: 'sparkline').html_safe
|
98
212
|
end
|
data/lib/tricle/mailer.rb
CHANGED
@@ -6,18 +6,18 @@ require_relative 'email_helper'
|
|
6
6
|
require_relative 'presenters/report'
|
7
7
|
require_relative 'time'
|
8
8
|
|
9
|
-
|
10
9
|
module Tricle
|
11
10
|
class Mailer < ActionMailer::Base
|
12
11
|
include ActiveSupport::DescendantsTracker
|
13
12
|
|
14
13
|
class_attribute :report
|
14
|
+
class_attribute :period
|
15
|
+
self.period = :week # or :day, :month
|
15
16
|
helper Tricle::EmailHelper
|
16
17
|
self.view_paths = File.dirname(__FILE__)
|
17
18
|
|
18
19
|
CSS = File.read(File.join(File.dirname(__FILE__), 'templates', 'email.css')).freeze
|
19
20
|
|
20
|
-
|
21
21
|
def subject
|
22
22
|
"Your #{self.class.name.titleize}"
|
23
23
|
end
|
@@ -62,8 +62,34 @@ module Tricle
|
|
62
62
|
self.report.add_list(klass, opts, &block)
|
63
63
|
end
|
64
64
|
|
65
|
-
def
|
66
|
-
|
65
|
+
def send_today?
|
66
|
+
time = Tricle::Time.new
|
67
|
+
|
68
|
+
case self.period
|
69
|
+
when :day
|
70
|
+
true
|
71
|
+
when :week
|
72
|
+
time.beginning_of_week?
|
73
|
+
when :month
|
74
|
+
time.beginning_of_month?
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def send_at_period
|
79
|
+
send_mailers(Tricle::Mailer.descendants.select(&:send_today?))
|
80
|
+
end
|
81
|
+
|
82
|
+
def send_all(with_period = nil)
|
83
|
+
klasses = Tricle::Mailer.descendants.select do |klass|
|
84
|
+
!with_period || (klass.period == with_period)
|
85
|
+
end
|
86
|
+
|
87
|
+
send_mailers(klasses)
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
def send_mailers(mailers)
|
67
93
|
puts "Sending #{mailers.size} emails..."
|
68
94
|
mailers.each do |klass|
|
69
95
|
puts "Sending #{klass.name}..."
|
@@ -71,15 +97,6 @@ module Tricle
|
|
71
97
|
end
|
72
98
|
puts "Done."
|
73
99
|
end
|
74
|
-
|
75
|
-
def send_all_if_beginning_of_week
|
76
|
-
time = Tricle::Time.new
|
77
|
-
if time.beginning_of_week?
|
78
|
-
self.send_all
|
79
|
-
else
|
80
|
-
puts "Skipping send, because it's not the beginning of the week."
|
81
|
-
end
|
82
|
-
end
|
83
100
|
end
|
84
101
|
end
|
85
102
|
end
|
data/lib/tricle/tasks.rb
CHANGED
@@ -16,10 +16,24 @@ namespace :tricle do
|
|
16
16
|
Tricle::Mailer.send_all
|
17
17
|
end
|
18
18
|
|
19
|
+
task :daily do
|
20
|
+
Tricle::Mailer.send(:day)
|
21
|
+
end
|
22
|
+
|
23
|
+
task :weekly do
|
24
|
+
Tricle::Mailer.send(:week)
|
25
|
+
end
|
26
|
+
|
27
|
+
task :monthly do
|
28
|
+
Tricle::Mailer.send(:month)
|
29
|
+
end
|
30
|
+
|
19
31
|
# needed for Heroku Scheduler, whose most infrequent option is daily
|
20
|
-
|
21
|
-
|
22
|
-
Tricle::Mailer.send_all_if_beginning_of_week
|
32
|
+
task :send_at_period do
|
33
|
+
Tricle::Mailer.send_at_period
|
23
34
|
end
|
35
|
+
|
36
|
+
# Backwards-compatibility
|
37
|
+
task send_after_beginning_of_week: [:send_at_period]
|
24
38
|
end
|
25
39
|
end
|
@@ -15,25 +15,25 @@
|
|
15
15
|
<tr>
|
16
16
|
<th><!--Title--></th>
|
17
17
|
<th>
|
18
|
-
<div
|
19
|
-
<%=
|
18
|
+
<div><%= old_dates_cell_header %></div>
|
19
|
+
<%= old_dates_cell %>
|
20
20
|
</th>
|
21
21
|
<th>
|
22
|
-
<div
|
23
|
-
<%=
|
22
|
+
<div><%= previous_dates_cell_header %></div>
|
23
|
+
<%= previous_dates_cell %>
|
24
24
|
</th>
|
25
25
|
<th>
|
26
|
-
<div
|
27
|
-
<%=
|
26
|
+
<div><%= current_dates_cell_header %></div>
|
27
|
+
<%= current_dates_cell %>
|
28
28
|
</th>
|
29
29
|
</tr>
|
30
30
|
<% section.metrics.each do |metric| %>
|
31
31
|
<tr>
|
32
32
|
<th class="metric-title" rowspan="2"><%= metric.title %></th>
|
33
|
-
<%=
|
34
|
-
<%=
|
33
|
+
<%= old_data_cell(metric) %>
|
34
|
+
<%= previous_data_cell(metric) %>
|
35
35
|
<td>
|
36
|
-
<div><%=
|
36
|
+
<div><%= current_number(metric) %></div>
|
37
37
|
<% if metric.total? %>
|
38
38
|
<div><%= format_number(metric.total) %> (total)</div>
|
39
39
|
<% end %>
|
data/lib/tricle/time.rb
CHANGED
@@ -10,10 +10,18 @@ module Tricle
|
|
10
10
|
self.time.strftime('%A').downcase.to_sym
|
11
11
|
end
|
12
12
|
|
13
|
+
def day_of_month
|
14
|
+
self.time.strftime('%-d').to_i
|
15
|
+
end
|
16
|
+
|
13
17
|
def beginning_of_week?
|
14
18
|
self.day_of_week == self.class.beginning_of_week
|
15
19
|
end
|
16
20
|
|
21
|
+
def beginning_of_month?
|
22
|
+
self.day_of_month == 1
|
23
|
+
end
|
24
|
+
|
17
25
|
## delegate methods ##
|
18
26
|
|
19
27
|
def beginning_of_day
|
@@ -24,6 +32,10 @@ module Tricle
|
|
24
32
|
self.time.beginning_of_week
|
25
33
|
end
|
26
34
|
|
35
|
+
def beginning_of_month
|
36
|
+
self.time.beginning_of_month
|
37
|
+
end
|
38
|
+
|
27
39
|
######################
|
28
40
|
|
29
41
|
class << self
|
data/lib/tricle/version.rb
CHANGED
@@ -0,0 +1,13 @@
|
|
1
|
+
require_relative '../../lib/tricle/mailer'
|
2
|
+
require_relative 'daily_test_metric'
|
3
|
+
|
4
|
+
class DailyTestMailer < Tricle::Mailer
|
5
|
+
default(
|
6
|
+
to: ['recipient1@test.com', 'recipient2@test.com'],
|
7
|
+
from: 'sender@test.com'
|
8
|
+
)
|
9
|
+
|
10
|
+
self.period = :day
|
11
|
+
|
12
|
+
metric DailyTestMetric
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require_relative '../../lib/tricle/mailer'
|
2
|
+
require_relative 'monthly_test_metric'
|
3
|
+
|
4
|
+
class MonthlyTestMailer < Tricle::Mailer
|
5
|
+
default(
|
6
|
+
to: ['recipient1@test.com', 'recipient2@test.com'],
|
7
|
+
from: 'sender@test.com'
|
8
|
+
)
|
9
|
+
|
10
|
+
self.period = :month
|
11
|
+
|
12
|
+
metric MonthlyTestMetric
|
13
|
+
end
|
@@ -10,8 +10,12 @@ class TestMetricWithNoTotal < Tricle::Metric
|
|
10
10
|
self.load_data
|
11
11
|
end
|
12
12
|
|
13
|
+
def fixture_filename
|
14
|
+
'weeks.csv'
|
15
|
+
end
|
16
|
+
|
13
17
|
def load_data
|
14
|
-
filename = File.join(File.dirname(__FILE__), '..', 'fixtures',
|
18
|
+
filename = File.join(File.dirname(__FILE__), '..', 'fixtures', fixture_filename)
|
15
19
|
data = CSV.read(filename)
|
16
20
|
|
17
21
|
self.data_by_start_on = Tricle::RangeData.new
|
@@ -0,0 +1,12 @@
|
|
1
|
+
2012-08-01,whatever,149
|
2
|
+
2012-09-01,whatever,112
|
3
|
+
2012-10-01,whatever,92
|
4
|
+
2012-11-01,whatever,1220
|
5
|
+
2012-12-01,whatever,12
|
6
|
+
2013-01-01,whatever,124
|
7
|
+
2013-02-01,whatever,139
|
8
|
+
2013-03-01,whatever,123
|
9
|
+
2013-04-01,whatever,152.6
|
10
|
+
2013-05-01,whatever,143
|
11
|
+
2013-06-01,whatever,200
|
12
|
+
2013-07-01,whatever,429
|
@@ -4,45 +4,37 @@ require_relative '../../lib/tricle/aggregation'
|
|
4
4
|
describe Tricle::Aggregation do
|
5
5
|
let(:metric) { TestMetric.new }
|
6
6
|
|
7
|
-
describe '#
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
describe '#periods_ago' do
|
8
|
+
context 'day' do
|
9
|
+
it "should start and end at midnight" do
|
10
|
+
expect(metric).to receive(:size_for_range).with(Time.new(2013, 7, 29), Time.new(2013, 7, 30))
|
11
|
+
metric.periods_ago(:day, 3)
|
12
|
+
end
|
11
13
|
end
|
12
|
-
end
|
13
|
-
|
14
|
-
describe '#yesterday' do
|
15
|
-
it "should start and end at midnight" do
|
16
|
-
expect(metric).to receive(:size_for_range).with(Time.new(2013, 7, 31), Time.new(2013, 8, 1))
|
17
|
-
metric.yesterday
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
describe '#weeks_ago' do
|
22
|
-
it "should start and end on Monday" do
|
23
|
-
expect(metric).to receive(:size_for_range).with(Time.new(2013, 7, 8), Time.new(2013, 7, 15))
|
24
|
-
metric.weeks_ago(3)
|
25
|
-
end
|
26
|
-
end
|
27
14
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
15
|
+
context 'week' do
|
16
|
+
it "should start and end on Monday" do
|
17
|
+
expect(metric).to receive(:size_for_range).with(Time.new(2013, 7, 8), Time.new(2013, 7, 15))
|
18
|
+
metric.periods_ago(:week, 3)
|
19
|
+
end
|
32
20
|
end
|
33
21
|
end
|
34
22
|
|
35
|
-
describe '#
|
36
|
-
|
37
|
-
|
38
|
-
|
23
|
+
describe '#range_values' do
|
24
|
+
context 'week' do
|
25
|
+
it "should return the values by week ascending" do
|
26
|
+
expect(metric).to receive(:periods_ago) {|period, n| n }.exactly(5).times
|
27
|
+
expect(metric.range_values(:week, 5)).to eq([5,4,3,2,1])
|
28
|
+
end
|
39
29
|
end
|
40
30
|
end
|
41
31
|
|
42
|
-
describe '#
|
43
|
-
|
44
|
-
|
45
|
-
|
32
|
+
describe '#range_average' do
|
33
|
+
context 'week' do
|
34
|
+
it "should average the values provided by #size_for_range" do
|
35
|
+
expect(metric).to receive(:size_for_range).exactly(13).times.and_return(1)
|
36
|
+
expect(metric.range_average(:week, 13)).to eq(1)
|
37
|
+
end
|
46
38
|
end
|
47
39
|
end
|
48
40
|
end
|
data/spec/unit/mailer_spec.rb
CHANGED
@@ -5,6 +5,8 @@ require_relative '../app/list_test_mailer'
|
|
5
5
|
require_relative '../app/list_test_mailer_with_options'
|
6
6
|
require_relative '../app/no_total_test_mailer'
|
7
7
|
require_relative '../app/test_mailer'
|
8
|
+
require_relative '../app/daily_test_mailer'
|
9
|
+
require_relative '../app/monthly_test_mailer'
|
8
10
|
|
9
11
|
describe Tricle::Mailer do
|
10
12
|
def deliver(klass)
|
@@ -45,6 +47,50 @@ describe Tricle::Mailer do
|
|
45
47
|
end
|
46
48
|
end
|
47
49
|
|
50
|
+
describe 'daily email' do
|
51
|
+
before do
|
52
|
+
deliver(DailyTestMailer)
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'includes the correct cell headers' do
|
56
|
+
expect(markup).to include('2 days ago')
|
57
|
+
expect(markup).to include('Yesterday')
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'includes the correct data' do
|
61
|
+
expect(markup).to include('14.1')
|
62
|
+
expect(markup).to include('20.0')
|
63
|
+
expect(markup).to include('11.0')
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'includes the correct averages' do
|
67
|
+
expect(markup).to include('-22.2')
|
68
|
+
expect(markup).to include('-45.0')
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe 'monthly email' do
|
73
|
+
before do
|
74
|
+
deliver(MonthlyTestMailer)
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'includes the correct cell headers' do
|
78
|
+
expect(markup).to include('Previous month')
|
79
|
+
expect(markup).to include('Last month')
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'includes the correct data' do
|
83
|
+
expect(markup).to include('241')
|
84
|
+
expect(markup).to include('200')
|
85
|
+
expect(markup).to include('429')
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'includes the correct averages' do
|
89
|
+
expect(markup).to include('77.8')
|
90
|
+
expect(markup).to include('114.0')
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
48
94
|
it "should exclude the total if not defined" do
|
49
95
|
deliver(NoTotalTestMailer)
|
50
96
|
expect(markup).to_not include('total')
|
@@ -74,23 +120,31 @@ describe Tricle::Mailer do
|
|
74
120
|
end
|
75
121
|
end
|
76
122
|
|
77
|
-
describe '.
|
78
|
-
it "should .deliver
|
79
|
-
Tricle::
|
80
|
-
|
123
|
+
describe '.send_at_period' do
|
124
|
+
it "should .deliver only mailers for the correct period" do
|
125
|
+
allow_any_instance_of(Tricle::Time).to receive(:beginning_of_week?).
|
126
|
+
and_return(false)
|
127
|
+
|
128
|
+
allow_any_instance_of(Tricle::Time).to receive(:beginning_of_month?).
|
129
|
+
and_return(false)
|
130
|
+
|
131
|
+
expect {
|
132
|
+
Tricle::Mailer.send_at_period
|
133
|
+
}.to change { ActionMailer::Base.deliveries.length }.by(1)
|
81
134
|
end
|
82
135
|
end
|
83
136
|
|
84
|
-
describe '.
|
85
|
-
it
|
86
|
-
expect
|
87
|
-
|
137
|
+
describe '.send_all' do
|
138
|
+
it 'sends all mailers' do
|
139
|
+
expect {
|
140
|
+
Tricle::Mailer.send_all
|
141
|
+
}.to change { ActionMailer::Base.deliveries.length }.by(7)
|
88
142
|
end
|
89
143
|
|
90
|
-
it
|
91
|
-
|
92
|
-
|
93
|
-
|
144
|
+
it 'sends a filtered segment of mailers' do
|
145
|
+
expect {
|
146
|
+
Tricle::Mailer.send_all(:week)
|
147
|
+
}.to change { ActionMailer::Base.deliveries.length }.by(5)
|
94
148
|
end
|
95
149
|
end
|
96
150
|
end
|
@@ -5,15 +5,15 @@ require_relative '../app/test_metric'
|
|
5
5
|
describe TestMetric do
|
6
6
|
let(:metric) { TestMetric.new }
|
7
7
|
|
8
|
-
describe '#
|
8
|
+
describe '#periods_ago' do
|
9
9
|
it "should start and end on Monday" do
|
10
|
-
expect(metric.
|
10
|
+
expect(metric.periods_ago(:week, 3)).to eq(51)
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
14
|
describe '#last_week' do
|
15
15
|
it "should start and end on Monday" do
|
16
|
-
expect(metric.
|
16
|
+
expect(metric.range_values(:week, 1)).to eq([62])
|
17
17
|
end
|
18
18
|
end
|
19
19
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tricle
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aidan Feldman
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-10-
|
11
|
+
date: 2014-10-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionmailer
|
@@ -135,10 +135,15 @@ files:
|
|
135
135
|
- lib/tricle/version.rb
|
136
136
|
- screenshot.png
|
137
137
|
- script/release
|
138
|
+
- spec/app/daily_test_mailer.rb
|
139
|
+
- spec/app/daily_test_metric.rb
|
138
140
|
- spec/app/group_test_mailer.rb
|
139
141
|
- spec/app/list_test_mailer.rb
|
140
142
|
- spec/app/list_test_mailer_with_options.rb
|
143
|
+
- spec/app/monthly_test_mailer.rb
|
144
|
+
- spec/app/monthly_test_metric.rb
|
141
145
|
- spec/app/no_total_test_mailer.rb
|
146
|
+
- spec/app/random_test_metric.rb
|
142
147
|
- spec/app/test_active_record_metric.rb
|
143
148
|
- spec/app/test_mailer.rb
|
144
149
|
- spec/app/test_metric.rb
|
@@ -147,6 +152,8 @@ files:
|
|
147
152
|
- spec/app/uber_test_mailer.rb
|
148
153
|
- spec/config/timecop.rb
|
149
154
|
- spec/fixture_generator
|
155
|
+
- spec/fixtures/days.csv
|
156
|
+
- spec/fixtures/months.csv
|
150
157
|
- spec/fixtures/weeks.csv
|
151
158
|
- spec/presenters/group_spec.rb
|
152
159
|
- spec/presenters/report_spec.rb
|
@@ -188,10 +195,15 @@ summary: A datastore-agnostic mailer where you can define custom metrics, where
|
|
188
195
|
can query SQL, MongoDB, external APIs, etc. to generate the stats you need. It
|
189
196
|
can be used within a larger project (e.g. Rails), or standalone.
|
190
197
|
test_files:
|
198
|
+
- spec/app/daily_test_mailer.rb
|
199
|
+
- spec/app/daily_test_metric.rb
|
191
200
|
- spec/app/group_test_mailer.rb
|
192
201
|
- spec/app/list_test_mailer.rb
|
193
202
|
- spec/app/list_test_mailer_with_options.rb
|
203
|
+
- spec/app/monthly_test_mailer.rb
|
204
|
+
- spec/app/monthly_test_metric.rb
|
194
205
|
- spec/app/no_total_test_mailer.rb
|
206
|
+
- spec/app/random_test_metric.rb
|
195
207
|
- spec/app/test_active_record_metric.rb
|
196
208
|
- spec/app/test_mailer.rb
|
197
209
|
- spec/app/test_metric.rb
|
@@ -200,6 +212,8 @@ test_files:
|
|
200
212
|
- spec/app/uber_test_mailer.rb
|
201
213
|
- spec/config/timecop.rb
|
202
214
|
- spec/fixture_generator
|
215
|
+
- spec/fixtures/days.csv
|
216
|
+
- spec/fixtures/months.csv
|
203
217
|
- spec/fixtures/weeks.csv
|
204
218
|
- spec/presenters/group_spec.rb
|
205
219
|
- spec/presenters/report_spec.rb
|