tricle 0.1.0

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.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +4 -0
  5. data/CONTRIBUTING.md +23 -0
  6. data/Gemfile +4 -0
  7. data/Guardfile +8 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +204 -0
  10. data/Rakefile +19 -0
  11. data/lib/tricle.rb +4 -0
  12. data/lib/tricle/abstract_method_error.rb +8 -0
  13. data/lib/tricle/email_helper.rb +66 -0
  14. data/lib/tricle/mail_preview.rb +10 -0
  15. data/lib/tricle/mailer.rb +75 -0
  16. data/lib/tricle/metric.rb +23 -0
  17. data/lib/tricle/presenters/group.rb +20 -0
  18. data/lib/tricle/presenters/list.rb +27 -0
  19. data/lib/tricle/presenters/metric.rb +51 -0
  20. data/lib/tricle/presenters/report.rb +40 -0
  21. data/lib/tricle/presenters/section.rb +9 -0
  22. data/lib/tricle/range_data.rb +27 -0
  23. data/lib/tricle/tasks.rb +19 -0
  24. data/lib/tricle/templates/email.css +47 -0
  25. data/lib/tricle/templates/email.html.erb +45 -0
  26. data/lib/tricle/templates/email.text.erb +2 -0
  27. data/lib/tricle/version.rb +3 -0
  28. data/screenshot.png +0 -0
  29. data/spec/app/group_test_mailer.rb +14 -0
  30. data/spec/app/list_test_mailer.rb +10 -0
  31. data/spec/app/test_mailer.rb +12 -0
  32. data/spec/app/test_metric.rb +39 -0
  33. data/spec/app/test_metric_with_long_name.rb +4 -0
  34. data/spec/app/uber_test_mailer.rb +20 -0
  35. data/spec/config/timecop.rb +7 -0
  36. data/spec/fixture_generator +18 -0
  37. data/spec/fixtures/weeks.csv +13 -0
  38. data/spec/presenters/group_spec.rb +17 -0
  39. data/spec/presenters/metric_spec.rb +42 -0
  40. data/spec/presenters/report_spec.rb +19 -0
  41. data/spec/spec_helper.rb +35 -0
  42. data/spec/unit/abstract_method_error_spec.rb +16 -0
  43. data/spec/unit/email_helper_spec.rb +43 -0
  44. data/spec/unit/mail_preview_spec.rb +15 -0
  45. data/spec/unit/mailer_spec.rb +66 -0
  46. data/spec/unit/metric_spec.rb +18 -0
  47. data/spec/unit/range_data_spec.rb +24 -0
  48. data/spec/unit/test_metric_spec.rb +20 -0
  49. data/tricle.gemspec +37 -0
  50. metadata +324 -0
@@ -0,0 +1,7 @@
1
+ require 'timecop'
2
+
3
+ def reset_time
4
+ # need to freeze the time for the TestMetric
5
+ now = Time.new(2013, 8, 1, 1, 0, 0, '-04:00')
6
+ Timecop.freeze(now)
7
+ end
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'csv'
4
+ require 'active_support/all'
5
+
6
+ end_at = Time.now.beginning_of_week
7
+ filename = File.join(File.dirname(__FILE__), 'fixtures', 'weeks.csv')
8
+ CSV.open(filename, 'wb') do |csv|
9
+ (0..12).reverse_each do |n|
10
+ week_start_at = end_at - (n + 1).weeks
11
+ week_end_at = end_at - n.weeks
12
+ csv << [
13
+ week_start_at.to_date,
14
+ week_end_at.to_date,
15
+ rand(100)
16
+ ]
17
+ end
18
+ end
@@ -0,0 +1,13 @@
1
+ 2013-04-29,2013-05-06,96
2
+ 2013-05-06,2013-05-13,83
3
+ 2013-05-13,2013-05-20,82
4
+ 2013-05-20,2013-05-27,16
5
+ 2013-05-27,2013-06-03,70
6
+ 2013-06-03,2013-06-10,67
7
+ 2013-06-10,2013-06-17,76
8
+ 2013-06-17,2013-06-24,75
9
+ 2013-06-24,2013-07-01,11
10
+ 2013-07-01,2013-07-08,19
11
+ 2013-07-08,2013-07-15,51
12
+ 2013-07-15,2013-07-22,79
13
+ 2013-07-22,2013-07-29,62
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+ require_relative '../../lib/tricle/presenters/group'
3
+ require_relative '../app/test_metric'
4
+
5
+ describe Tricle::Presenters::Group do
6
+ let(:group) { Tricle::Presenters::Group.new }
7
+
8
+ describe '#add_metric' do
9
+ it "should add a new metric instance" do
10
+ group.add_metric(TestMetric)
11
+ group.metric_presenters.size.should eq(1)
12
+ presenter = group.metric_presenters.first
13
+ presenter.should be_a(Tricle::Presenters::Metric)
14
+ presenter.metric.should be_a(TestMetric)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+ require_relative '../../lib/tricle/presenters/metric'
3
+
4
+ describe Tricle::Presenters::Metric do
5
+ let(:presenter) { Tricle::Presenters::Metric.new(TestMetric) }
6
+ let(:metric) { presenter.metric }
7
+
8
+ describe '#days_ago' do
9
+ it "should start and end at midnight" do
10
+ metric.should_receive(:size_for_range).with(Time.new(2013, 7, 29), Time.new(2013, 7, 30))
11
+ presenter.days_ago(3)
12
+ end
13
+ end
14
+
15
+ describe '#yesterday' do
16
+ it "should start and end at midnight" do
17
+ metric.should_receive(:size_for_range).with(Time.new(2013, 7, 31), Time.new(2013, 8, 1))
18
+ presenter.yesterday
19
+ end
20
+ end
21
+
22
+ describe '#weeks_ago' do
23
+ it "should start and end on Monday" do
24
+ metric.should_receive(:size_for_range).with(Time.new(2013, 7, 8), Time.new(2013, 7, 15))
25
+ presenter.weeks_ago(3)
26
+ end
27
+ end
28
+
29
+ describe '#last_week' do
30
+ it "should start and end on Monday" do
31
+ metric.should_receive(:size_for_range).with(Time.new(2013, 7, 22), Time.new(2013, 7, 29))
32
+ presenter.last_week
33
+ end
34
+ end
35
+
36
+ describe '#week_average_this_quarter' do
37
+ it "should average the values provided by #size_for_range" do
38
+ metric.should_receive(:size_for_range).exactly(13).times.and_return(1)
39
+ presenter.week_average_this_quarter.should eq(1)
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ require_relative '../../lib/tricle/presenters/report'
4
+
5
+ describe Tricle::Presenters::Report do
6
+ let(:report) { Tricle::Presenters::Report.new }
7
+
8
+ describe '#add_metric' do
9
+ it "should add a new group if none are present" do
10
+ report.sections.should eq([])
11
+ report.add_metric(TestMetric)
12
+ report.sections.size.should eq(1)
13
+
14
+ presenters = report.sections.first.metric_presenters
15
+ presenters.size.should eq(1)
16
+ presenters.first.metric.should be_a(TestMetric)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,35 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+
6
+ require 'rubygems'
7
+ require 'bundler/setup'
8
+ Bundler.setup
9
+
10
+ require 'action_mailer'
11
+ require 'timecop'
12
+
13
+ require_relative 'config/timecop'
14
+
15
+ # TODO find a less heavy-handed way of handling this
16
+ reset_time
17
+
18
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
19
+ RSpec.configure do |config|
20
+ config.treat_symbols_as_metadata_keys_with_true_values = true
21
+ config.run_all_when_everything_filtered = true
22
+ config.filter_run :focus
23
+
24
+ ActionMailer::Base.delivery_method = :test
25
+ config.before do
26
+ ActionMailer::Base.deliveries.clear
27
+ reset_time
28
+ end
29
+
30
+ # Run specs in random order to surface order dependencies. If you find an
31
+ # order dependency and want to debug it, you can fix the order by providing
32
+ # the seed, which is printed after each run.
33
+ # --seed 1234
34
+ config.order = 'random'
35
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+ require_relative '../../lib/tricle/abstract_method_error'
3
+
4
+ describe Tricle::AbstractMethodError do
5
+ class TestAbstractMethod
6
+ def foo
7
+ raise Tricle::AbstractMethodError.new
8
+ end
9
+ end
10
+
11
+ it "should include the method name in the message" do
12
+ expect {
13
+ TestAbstractMethod.new.foo
14
+ }.to raise_error("#foo not implemented")
15
+ end
16
+ end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+ require_relative '../../lib/tricle/email_helper'
3
+
4
+ describe Tricle::EmailHelper do
5
+ class HelperTester
6
+ include Tricle::EmailHelper
7
+ end
8
+
9
+ let(:helper) { HelperTester.new }
10
+
11
+ describe "#number_with_delimiter" do
12
+ it "should put commas between every three digits" do
13
+ helper.number_with_delimiter(1234567.89).should eq('1,234,567.89')
14
+ end
15
+ end
16
+
17
+ describe "#percent_change" do
18
+ it "should prefix positive values with a +" do
19
+ helper.percent_change(110, 100).should eq('+10.0%')
20
+ end
21
+
22
+ it "should prefix negative values with a -" do
23
+ helper.percent_change(90, 100).should eq('-10.0%')
24
+ end
25
+
26
+ it "should handle a zero as the old value with positive change" do
27
+ helper.percent_change(10, 0).should eq('+')
28
+ end
29
+
30
+ it "should handle a zero as the old value with negative change" do
31
+ helper.percent_change(-20, 0).should eq('-')
32
+ end
33
+ end
34
+
35
+ describe "#single_week_dates_cell" do
36
+ it "should not include the last day of the week" do
37
+ start_at = Time.new(2013, 7, 22) # a Monday
38
+ markup = helper.single_week_dates_cell(start_at)
39
+ markup.should include('7/22/13')
40
+ markup.should include('7/28/13')
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+ require_relative '../app/test_mailer'
3
+ require_relative '../../lib/tricle/mail_preview'
4
+
5
+ describe Tricle::MailPreview do
6
+ describe 'mailer methods' do
7
+ it "should have methods corresponding to all mailers" do
8
+ Tricle::MailPreview.instance_methods(false).should include(:test_mailer)
9
+ end
10
+
11
+ it "should return a Mail::Message" do
12
+ Tricle::MailPreview.new.test_mailer.should be_a(Mail::Message)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,66 @@
1
+ require 'spec_helper'
2
+ require_relative '../../lib/tricle/mailer'
3
+ require_relative '../app/group_test_mailer'
4
+ require_relative '../app/list_test_mailer'
5
+ require_relative '../app/test_mailer'
6
+
7
+ describe Tricle::Mailer do
8
+ def deliver(klass)
9
+ klass.email.deliver
10
+ ActionMailer::Base.deliveries.length.should eq(1)
11
+ end
12
+
13
+ let(:message) { ActionMailer::Base.deliveries.last }
14
+ let(:markup) { message.html_part.body.to_s }
15
+
16
+ describe '.email' do
17
+ before do
18
+ deliver(TestMailer)
19
+ end
20
+
21
+ it "should respect all the options in the 'default hash'" do
22
+ message.to.should eq(['recipient1@test.com', 'recipient2@test.com'])
23
+ message.from.should eq(['sender@test.com'])
24
+ end
25
+
26
+ it "should set the subject based on the class name" do
27
+ message.subject.should eq("Your Test Mailer")
28
+ end
29
+
30
+ it "should include the Metric values in the HTML part" do
31
+ markup.should include('Test Metric')
32
+ markup.should match(/\b62\b/) # last week
33
+ markup.should match(/\b787\b/) # total
34
+ end
35
+
36
+ it "should link to the Issues page in the text part" do
37
+ source = message.text_part.body.to_s
38
+ source.should include('github.com/artsy/tricle')
39
+ end
40
+ end
41
+
42
+ describe '.group' do
43
+ it "should include the group title" do
44
+ deliver(GroupTestMailer)
45
+ markup.should include("Test Group 1")
46
+ markup.should include("Test Group 2")
47
+ markup.should include("Test Metric")
48
+ end
49
+ end
50
+
51
+ describe '.list' do
52
+ it "should include the list title" do
53
+ deliver(ListTestMailer)
54
+ markup.should include("Test Metric")
55
+ markup.should include('62.0')
56
+ markup.should_not include('79.0')
57
+ end
58
+ end
59
+
60
+ describe '.send_all' do
61
+ it "should .deliver all defined mailers" do
62
+ Tricle::Mailer.send_all
63
+ ActionMailer::Base.deliveries.length.should eq(3)
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ require_relative '../../lib/tricle/metric'
4
+
5
+ describe Tricle::Metric do
6
+ let(:metric) { Tricle::Metric.new }
7
+
8
+ describe '#size_for_range' do
9
+ it "should raise an exception if #items_for_range isn't overridden" do
10
+ expect { metric.size_for_range(Time.now.yesterday, Time.now) }.to raise_error
11
+ end
12
+
13
+ it "should use the number of items by default" do
14
+ metric.stub(:items_for_range) { [1,2,3] }
15
+ metric.size_for_range(Time.now.yesterday, Time.now).should eq(3)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+ require_relative '../../lib/tricle/range_data'
3
+
4
+ describe Tricle::RangeData do
5
+ let(:rd) { Tricle::RangeData.new }
6
+ before do
7
+ rd.add(10.days.ago, 5)
8
+ rd.add(5.days.ago, 6)
9
+ rd.add(1.day.ago, 7)
10
+ end
11
+
12
+ describe '#all_items' do
13
+ it "should return all the items" do
14
+ rd.all_items.sort.should eq([5, 6, 7])
15
+ end
16
+ end
17
+
18
+ describe '#items_for_range' do
19
+ it "should return the items for the days provided" do
20
+ items = rd.items_for_range(11.days.ago, 3.days.ago)
21
+ items.sort.should eq([5, 6])
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+ require_relative '../app/test_metric'
3
+ require_relative '../../lib/tricle/presenters/metric'
4
+
5
+ # test the tests
6
+ describe TestMetric do
7
+ let(:presenter) { Tricle::Presenters::Metric.new(TestMetric) }
8
+
9
+ describe '#weeks_ago' do
10
+ it "should start and end on Monday" do
11
+ presenter.weeks_ago(3).should eq(51)
12
+ end
13
+ end
14
+
15
+ describe '#last_week' do
16
+ it "should start and end on Monday" do
17
+ presenter.last_week.should eq(62)
18
+ end
19
+ end
20
+ end
data/tricle.gemspec ADDED
@@ -0,0 +1,37 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'tricle/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "tricle"
8
+ spec.version = Tricle::VERSION
9
+ spec.authors = ["Aidan Feldman"]
10
+ spec.email = ["aidan.feldman@gmail.com"]
11
+ spec.description = %q{Automated metrics reporting via email}
12
+ spec.summary = %q{A datastore-agnostic mailer where you can define custom metrics, where you can query SQL, MongoDB, external APIs, etc. to generate the stats you need. It can be used within a larger project (e.g. Rails), or standalone.}
13
+ spec.homepage = "https://github.com/artsy/tricle"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "actionmailer", "~> 4.0"
22
+ spec.add_dependency "activesupport", "~> 4.0"
23
+ spec.add_dependency "mail_view", "~> 1.0"
24
+ spec.add_dependency "nokogiri", "~> 1.6"
25
+ spec.add_dependency "premailer", "~> 1.7"
26
+ spec.add_dependency "rack", "~> 1.1"
27
+
28
+ spec.add_development_dependency "bundler", "~> 1.3"
29
+ spec.add_development_dependency "debugger"
30
+ spec.add_development_dependency "guard", "~> 1.8"
31
+ spec.add_development_dependency "guard-rspec"
32
+ spec.add_development_dependency "rake"
33
+ spec.add_development_dependency "rspec", "~> 2.14"
34
+ spec.add_development_dependency "ruby_gntp"
35
+ spec.add_development_dependency "shotgun"
36
+ spec.add_development_dependency "timecop", "~> 0.6.2"
37
+ end
metadata ADDED
@@ -0,0 +1,324 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tricle
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Aidan Feldman
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-08-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: actionmailer
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '4.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '4.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '4.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: mail_view
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '1.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '1.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: nokogiri
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '1.6'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '1.6'
69
+ - !ruby/object:Gem::Dependency
70
+ name: premailer
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: '1.7'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '1.7'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rack
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: '1.1'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ~>
95
+ - !ruby/object:Gem::Version
96
+ version: '1.1'
97
+ - !ruby/object:Gem::Dependency
98
+ name: bundler
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ~>
102
+ - !ruby/object:Gem::Version
103
+ version: '1.3'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ version: '1.3'
111
+ - !ruby/object:Gem::Dependency
112
+ name: debugger
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: guard
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ~>
130
+ - !ruby/object:Gem::Version
131
+ version: '1.8'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ~>
137
+ - !ruby/object:Gem::Version
138
+ version: '1.8'
139
+ - !ruby/object:Gem::Dependency
140
+ name: guard-rspec
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - '>='
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - '>='
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: rake
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - '>='
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - '>='
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: rspec
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ~>
172
+ - !ruby/object:Gem::Version
173
+ version: '2.14'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ~>
179
+ - !ruby/object:Gem::Version
180
+ version: '2.14'
181
+ - !ruby/object:Gem::Dependency
182
+ name: ruby_gntp
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - '>='
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - '>='
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
195
+ - !ruby/object:Gem::Dependency
196
+ name: shotgun
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - '>='
200
+ - !ruby/object:Gem::Version
201
+ version: '0'
202
+ type: :development
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - '>='
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
209
+ - !ruby/object:Gem::Dependency
210
+ name: timecop
211
+ requirement: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - ~>
214
+ - !ruby/object:Gem::Version
215
+ version: 0.6.2
216
+ type: :development
217
+ prerelease: false
218
+ version_requirements: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - ~>
221
+ - !ruby/object:Gem::Version
222
+ version: 0.6.2
223
+ description: Automated metrics reporting via email
224
+ email:
225
+ - aidan.feldman@gmail.com
226
+ executables: []
227
+ extensions: []
228
+ extra_rdoc_files: []
229
+ files:
230
+ - .gitignore
231
+ - .rspec
232
+ - .travis.yml
233
+ - CONTRIBUTING.md
234
+ - Gemfile
235
+ - Guardfile
236
+ - LICENSE.txt
237
+ - README.md
238
+ - Rakefile
239
+ - lib/tricle.rb
240
+ - lib/tricle/abstract_method_error.rb
241
+ - lib/tricle/email_helper.rb
242
+ - lib/tricle/mail_preview.rb
243
+ - lib/tricle/mailer.rb
244
+ - lib/tricle/metric.rb
245
+ - lib/tricle/presenters/group.rb
246
+ - lib/tricle/presenters/list.rb
247
+ - lib/tricle/presenters/metric.rb
248
+ - lib/tricle/presenters/report.rb
249
+ - lib/tricle/presenters/section.rb
250
+ - lib/tricle/range_data.rb
251
+ - lib/tricle/tasks.rb
252
+ - lib/tricle/templates/email.css
253
+ - lib/tricle/templates/email.html.erb
254
+ - lib/tricle/templates/email.text.erb
255
+ - lib/tricle/version.rb
256
+ - screenshot.png
257
+ - spec/app/group_test_mailer.rb
258
+ - spec/app/list_test_mailer.rb
259
+ - spec/app/test_mailer.rb
260
+ - spec/app/test_metric.rb
261
+ - spec/app/test_metric_with_long_name.rb
262
+ - spec/app/uber_test_mailer.rb
263
+ - spec/config/timecop.rb
264
+ - spec/fixture_generator
265
+ - spec/fixtures/weeks.csv
266
+ - spec/presenters/group_spec.rb
267
+ - spec/presenters/metric_spec.rb
268
+ - spec/presenters/report_spec.rb
269
+ - spec/spec_helper.rb
270
+ - spec/unit/abstract_method_error_spec.rb
271
+ - spec/unit/email_helper_spec.rb
272
+ - spec/unit/mail_preview_spec.rb
273
+ - spec/unit/mailer_spec.rb
274
+ - spec/unit/metric_spec.rb
275
+ - spec/unit/range_data_spec.rb
276
+ - spec/unit/test_metric_spec.rb
277
+ - tricle.gemspec
278
+ homepage: https://github.com/artsy/tricle
279
+ licenses:
280
+ - MIT
281
+ metadata: {}
282
+ post_install_message:
283
+ rdoc_options: []
284
+ require_paths:
285
+ - lib
286
+ required_ruby_version: !ruby/object:Gem::Requirement
287
+ requirements:
288
+ - - '>='
289
+ - !ruby/object:Gem::Version
290
+ version: '0'
291
+ required_rubygems_version: !ruby/object:Gem::Requirement
292
+ requirements:
293
+ - - '>='
294
+ - !ruby/object:Gem::Version
295
+ version: '0'
296
+ requirements: []
297
+ rubyforge_project:
298
+ rubygems_version: 2.0.3
299
+ signing_key:
300
+ specification_version: 4
301
+ summary: A datastore-agnostic mailer where you can define custom metrics, where you
302
+ can query SQL, MongoDB, external APIs, etc. to generate the stats you need. It
303
+ can be used within a larger project (e.g. Rails), or standalone.
304
+ test_files:
305
+ - spec/app/group_test_mailer.rb
306
+ - spec/app/list_test_mailer.rb
307
+ - spec/app/test_mailer.rb
308
+ - spec/app/test_metric.rb
309
+ - spec/app/test_metric_with_long_name.rb
310
+ - spec/app/uber_test_mailer.rb
311
+ - spec/config/timecop.rb
312
+ - spec/fixture_generator
313
+ - spec/fixtures/weeks.csv
314
+ - spec/presenters/group_spec.rb
315
+ - spec/presenters/metric_spec.rb
316
+ - spec/presenters/report_spec.rb
317
+ - spec/spec_helper.rb
318
+ - spec/unit/abstract_method_error_spec.rb
319
+ - spec/unit/email_helper_spec.rb
320
+ - spec/unit/mail_preview_spec.rb
321
+ - spec/unit/mailer_spec.rb
322
+ - spec/unit/metric_spec.rb
323
+ - spec/unit/range_data_spec.rb
324
+ - spec/unit/test_metric_spec.rb