tricle 0.2.4 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|