reparty 0.2.1 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
data/History.md CHANGED
@@ -1,3 +1,13 @@
1
+ ## 0.3.1
2
+
3
+ - Total graphs were off by one day
4
+
5
+ ## 0.3.0
6
+
7
+ - Add Sendgrid report
8
+ - A few more possibly timezone fixes
9
+ - Add HTTParty as a dependency. (Great library name, by the way!)
10
+
1
11
  ## 0.2.1
2
12
 
3
13
  - Timezone fix (ActiveRecord always saves in UTC)
@@ -0,0 +1,10 @@
1
+ <table width="545" cellpadding="0" cellspacing="25" border="0">
2
+ <tr>
3
+ <td align="left">
4
+ <h3><%= report.title %></h3>
5
+ </td>
6
+ </tr>
7
+ <tr>
8
+ <td align="center"><%= image_tag attachments["#{report.hash}.png"].url, border: 0, align: "center" %></td>
9
+ </tr>
10
+ </table>
@@ -36,7 +36,7 @@ module Reparty
36
36
 
37
37
  def daily_dataset
38
38
  if @operation == :total
39
- 7.downto(1).map { |x| @model.where("#{@field.to_s} < ?", DateTime.now.utc.at_midnight-x).send(:count, @field) }
39
+ 6.downto(0).map { |x| @model.where("#{@field.to_s} < ?", DateTime.now.utc.at_midnight-x).send(:count, @field) }
40
40
  else
41
41
  7.downto(1).map { |x| @model.where("DATE(#{@field.to_s}) = ?", DateTime.now.utc.to_date-x).send(@operation, @field) }
42
42
  end
@@ -44,7 +44,7 @@ module Reparty
44
44
 
45
45
  def yesterday
46
46
  op = @operation == :total ? :count : @operation
47
- @model.where("DATE(#{@field.to_s}) = ?", DateTime.now-1).send(op, @field)
47
+ @model.where("DATE(#{@field.to_s}) = ?", DateTime.now.utc.to_date-1).send(op, @field)
48
48
  end
49
49
 
50
50
  def total
@@ -0,0 +1,46 @@
1
+ require 'httparty'
2
+
3
+ module Reparty
4
+ class Report
5
+ class Sendgrid < Report
6
+ include HTTParty
7
+ format :json
8
+ headers 'Content-Type' => 'application/json', 'Accept' => 'application/json'
9
+
10
+ attr_reader :api_user, :api_key
11
+
12
+ def initialize(*args, &block)
13
+ super(args.shift)
14
+
15
+ @api_user = args.shift
16
+ @api_key = args.shift
17
+
18
+ @color = "#287abe"
19
+ end
20
+
21
+ def attach(attachments)
22
+ @graph = build_daily_graph
23
+
24
+ %W{requests delivered bounces spamreports}.each do |stat|
25
+ @graph.data(stat.capitalize, stats.map{|s| s.fetch(stat,0)})
26
+ end
27
+
28
+ attachments.inline["#{self.hash}.png"] = @graph.to_blob
29
+ end
30
+
31
+ def stats(today=DateTime.now)
32
+ @stats ||= self.class.get(
33
+ "https://sendgrid.com/api/stats.get.json?" +
34
+ "api_user=" + @api_user +
35
+ "&api_key=" + @api_key +
36
+ "&start_date=" + (today.utc.to_date - 1).strftime("%Y-%m-%d") +
37
+ "&days=7",
38
+ options: { format: 'json' }
39
+ )
40
+
41
+ @stats.pop if @stats.size == 8
42
+ @stats
43
+ end
44
+ end
45
+ end
46
+ end
@@ -16,10 +16,10 @@ module Reparty
16
16
 
17
17
  protected
18
18
 
19
- def build_daily_graph
19
+ def build_daily_graph(start_date=DateTime.now.utc)
20
20
  g = Gruff::Line.new(545)
21
21
  g.title = @title
22
- g.labels = Hash[*(1..7).map{|x| [x-1, (DateTime.now - (8-x)).strftime("%-m/%-d")] }.flatten]
22
+ g.labels = Hash[*(1..7).map{|x| [x-1, (start_date - (8-x)).strftime("%-m/%-d")] }.flatten]
23
23
  g
24
24
  end
25
25
  end
@@ -1,3 +1,3 @@
1
1
  module Reparty
2
- VERSION = "0.2.1"
2
+ VERSION = "0.3.1"
3
3
  end
data/lib/reparty.rb CHANGED
@@ -1,9 +1,11 @@
1
1
  require "reparty/version"
2
2
 
3
3
  require "reparty/config"
4
+ require "reparty/email"
5
+
4
6
  require "reparty/report"
5
7
  require "reparty/report/active_record"
6
- require "reparty/email"
8
+ require "reparty/report/sendgrid"
7
9
 
8
10
  require "reparty/engine"
9
11
 
data/reparty.gemspec CHANGED
@@ -24,10 +24,13 @@ Gem::Specification.new do |spec|
24
24
  spec.add_dependency "rmagick"
25
25
  spec.add_dependency "gruff"
26
26
  spec.add_dependency "roadie"
27
+ spec.add_dependency "httparty"
27
28
 
28
29
  spec.add_development_dependency "bundler", "~> 1.3"
29
30
  spec.add_development_dependency "rake"
30
31
  spec.add_development_dependency "rspec"
31
- spec.add_development_dependency "sqlite3"
32
32
  spec.add_development_dependency "letter_opener"
33
+ spec.add_development_dependency "webmock"
34
+ spec.add_development_dependency "vcr"
35
+ spec.add_development_dependency "sqlite3"
33
36
  end
@@ -0,0 +1,65 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://sendgrid.com/api/stats.get.json?api_key=<SENDGRID_PASSWORD>&api_user=<SENDGRID_USER>&days=7&start_date=2013-04-30
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Content-Type:
11
+ - application/json
12
+ Accept:
13
+ - application/json
14
+ response:
15
+ status:
16
+ code: 200
17
+ message: OK
18
+ headers:
19
+ Server:
20
+ - nginx/1.3.14
21
+ Date:
22
+ - Wed, 01 May 2013 07:04:44 GMT
23
+ Content-Type:
24
+ - text/html
25
+ Transfer-Encoding:
26
+ - chunked
27
+ Connection:
28
+ - keep-alive
29
+ body:
30
+ encoding: US-ASCII
31
+ string: ! '[{"delivered": 2363, "unsubscribes": 0, "invalid_email": 2, "bounces":
32
+ 18, "repeat_unsubscribes": 0, "unique_clicks": 0, "blocked": 2, "spam_drop":
33
+ 0, "repeat_bounces": 37, "repeat_spamreports": 0, "date": "2013-04-24", "requests":
34
+ 2419, "spamreports": 0, "clicks": 0, "opens": 0, "unique_opens": 0},{"delivered":
35
+ 3059, "unsubscribes": 0, "invalid_email": 2, "bounces": 31, "repeat_unsubscribes":
36
+ 0, "unique_clicks": 0, "blocked": 2, "spam_drop": 0, "repeat_bounces": 45,
37
+ "repeat_spamreports": 0, "date": "2013-04-25", "requests": 3133, "spamreports":
38
+ 0, "clicks": 0, "opens": 1, "unique_opens": 0},{"delivered": 3856, "unsubscribes":
39
+ 0, "invalid_email": 3, "bounces": 29, "repeat_unsubscribes": 0, "unique_clicks":
40
+ 0, "blocked": 2, "spam_drop": 0, "repeat_bounces": 78, "repeat_spamreports":
41
+ 0, "date": "2013-04-26", "requests": 3961, "spamreports": 0, "clicks": 0,
42
+ "opens": 0, "unique_opens": 0},{"delivered": 3784, "unsubscribes": 0, "invalid_email":
43
+ 3, "bounces": 5, "repeat_unsubscribes": 0, "unique_clicks": 0, "blocked":
44
+ 3, "spam_drop": 0, "repeat_bounces": 104, "repeat_spamreports": 0, "date":
45
+ "2013-04-27", "requests": 3899, "spamreports": 3, "clicks": 0, "opens": 0,
46
+ "unique_opens": 0},{"delivered": 2945, "unsubscribes": 0, "invalid_email":
47
+ 3, "bounces": 5, "repeat_unsubscribes": 0, "unique_clicks": 0, "blocked":
48
+ 6, "spam_drop": 0, "repeat_bounces": 78, "repeat_spamreports": 1, "date":
49
+ "2013-04-28", "requests": 3035, "spamreports": 0, "clicks": 0, "opens": 0,
50
+ "unique_opens": 0},{"delivered": 3218, "unsubscribes": 0, "invalid_email":
51
+ 3, "bounces": 2, "repeat_unsubscribes": 0, "unique_clicks": 0, "blocked":
52
+ 6, "spam_drop": 0, "repeat_bounces": 90, "repeat_spamreports": 0, "date":
53
+ "2013-04-29", "requests": 3317, "spamreports": 0, "clicks": 0, "opens": 0,
54
+ "unique_opens": 0},{"delivered": 4056, "unsubscribes": 0, "invalid_email":
55
+ 3, "bounces": 2, "repeat_unsubscribes": 0, "unique_clicks": 0, "blocked":
56
+ 5, "spam_drop": 0, "repeat_bounces": 115, "repeat_spamreports": 1, "date":
57
+ "2013-04-30", "requests": 4183, "spamreports": 0, "clicks": 0, "opens": 0,
58
+ "unique_opens": 0},{"delivered": 2, "unsubscribes": 0, "invalid_email": 0,
59
+ "bounces": 0, "repeat_unsubscribes": 0, "unique_clicks": 0, "blocked": 0,
60
+ "spam_drop": 0, "repeat_bounces": 0, "repeat_spamreports": 0, "date": "2013-05-01",
61
+ "requests": 2, "spamreports": 0, "clicks": 0, "opens": 0, "unique_opens":
62
+ 0}]'
63
+ http_version:
64
+ recorded_at: Wed, 01 May 2013 07:04:44 GMT
65
+ recorded_with: VCR 2.4.0
@@ -0,0 +1,25 @@
1
+ require_relative '../spec_helper'
2
+
3
+ describe Reparty::Report::Sendgrid, vcr: { cassette_name: "sendgrid" } do
4
+ let(:sendgrid_user) { ENV.fetch("SENDGRID_USER","admin@someplace.com") }
5
+ let(:sendgrid_pass) { ENV.fetch("SENDGRID_PASSWORD","asdfasdf") }
6
+
7
+ subject do
8
+ Reparty.config do |config|
9
+ config.add_report Reparty::Report::Sendgrid, "Sendgrid Emails", sendgrid_user, sendgrid_pass
10
+ end
11
+ Reparty.reports.last
12
+ end
13
+
14
+ it { should be_kind_of(Reparty::Report::Sendgrid) }
15
+ its(:api_user) { should == sendgrid_user }
16
+ its(:api_key) { should == sendgrid_pass }
17
+ its(:color) { should == "#287abe" }
18
+
19
+ it "gets stats" do
20
+ stats = subject.stats(DateTime.new(2013,5,1))
21
+ stats.size.should == 7
22
+ stats.first.should be_kind_of(Hash)
23
+ stats.first["delivered"].should == 2363
24
+ end
25
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
2
  require 'reparty'
3
+ require 'vcr_helper'
3
4
 
4
5
  Dir["./spec/support/**/*.rb"].sort.each {|f| require f}
5
6
 
@@ -41,6 +41,11 @@ describe "reparty:email" do
41
41
  {:name => "Someone", :score => 1, :created_at => DateTime.now - 8},
42
42
  ].each{|u| User.create!(u) }
43
43
 
44
+ Reparty.config do |config|
45
+ config.add_report Reparty::Report::ActiveRecord, "New User Signups", :user
46
+ config.add_report Reparty::Report::Sendgrid, "Sendgrid Emails", ENV["SENDGRID_USER"], ENV["SENDGRID_PASSWORD"]
47
+ end
48
+
44
49
  subject.invoke("test@test.com")
45
50
  end
46
51
  end
@@ -0,0 +1,13 @@
1
+ require "webmock/rspec"
2
+ require "vcr"
3
+
4
+ VCR.configure do |c|
5
+ c.cassette_library_dir = "spec/cassettes"
6
+ c.default_cassette_options = { :record => :new_episodes }
7
+ c.hook_into :webmock
8
+ c.configure_rspec_metadata!
9
+ c.allow_http_connections_when_no_cassette = true
10
+
11
+ c.filter_sensitive_data("<SENDGRID_USER>") { ENV.fetch("SENDGRID_USER","admin@someplace.com") }
12
+ c.filter_sensitive_data("<SENDGRID_PASSWORD>") { ENV.fetch("SENDGRID_PASSWORD","asdfasdf") }
13
+ end
metadata CHANGED
@@ -2,14 +2,14 @@
2
2
  name: reparty
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.2.1
5
+ version: 0.3.1
6
6
  platform: ruby
7
7
  authors:
8
8
  - Tim Dorr
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-05-01 00:00:00.000000000 Z
12
+ date: 2013-05-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: railties
@@ -107,6 +107,22 @@ dependencies:
107
107
  version: '0'
108
108
  none: false
109
109
  prerelease: false
110
+ - !ruby/object:Gem::Dependency
111
+ name: httparty
112
+ type: :runtime
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ none: false
119
+ version_requirements: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ! '>='
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ none: false
125
+ prerelease: false
110
126
  - !ruby/object:Gem::Dependency
111
127
  name: bundler
112
128
  type: :development
@@ -156,7 +172,7 @@ dependencies:
156
172
  none: false
157
173
  prerelease: false
158
174
  - !ruby/object:Gem::Dependency
159
- name: sqlite3
175
+ name: letter_opener
160
176
  type: :development
161
177
  requirement: !ruby/object:Gem::Requirement
162
178
  requirements:
@@ -172,7 +188,39 @@ dependencies:
172
188
  none: false
173
189
  prerelease: false
174
190
  - !ruby/object:Gem::Dependency
175
- name: letter_opener
191
+ name: webmock
192
+ type: :development
193
+ requirement: !ruby/object:Gem::Requirement
194
+ requirements:
195
+ - - ! '>='
196
+ - !ruby/object:Gem::Version
197
+ version: '0'
198
+ none: false
199
+ version_requirements: !ruby/object:Gem::Requirement
200
+ requirements:
201
+ - - ! '>='
202
+ - !ruby/object:Gem::Version
203
+ version: '0'
204
+ none: false
205
+ prerelease: false
206
+ - !ruby/object:Gem::Dependency
207
+ name: vcr
208
+ type: :development
209
+ requirement: !ruby/object:Gem::Requirement
210
+ requirements:
211
+ - - ! '>='
212
+ - !ruby/object:Gem::Version
213
+ version: '0'
214
+ none: false
215
+ version_requirements: !ruby/object:Gem::Requirement
216
+ requirements:
217
+ - - ! '>='
218
+ - !ruby/object:Gem::Version
219
+ version: '0'
220
+ none: false
221
+ prerelease: false
222
+ - !ruby/object:Gem::Dependency
223
+ name: sqlite3
176
224
  type: :development
177
225
  requirement: !ruby/object:Gem::Requirement
178
226
  requirements:
@@ -206,6 +254,7 @@ files:
206
254
  - app/assets/images/spacer.gif
207
255
  - app/mailers/report_mailer.rb
208
256
  - app/views/report_mailer/_active_record.html.erb
257
+ - app/views/report_mailer/_sendgrid.html.erb
209
258
  - app/views/report_mailer/daily.html.erb
210
259
  - lib/reparty.rb
211
260
  - lib/reparty/config.rb
@@ -213,16 +262,20 @@ files:
213
262
  - lib/reparty/engine.rb
214
263
  - lib/reparty/report.rb
215
264
  - lib/reparty/report/active_record.rb
265
+ - lib/reparty/report/sendgrid.rb
216
266
  - lib/reparty/version.rb
217
267
  - lib/tasks/reparty.rake
218
268
  - reparty.gemspec
269
+ - spec/cassettes/sendgrid.yml
219
270
  - spec/email_spec.rb
220
271
  - spec/reparty_spec.rb
221
272
  - spec/report/active_record_spec.rb
273
+ - spec/report/sendgrid_spec.rb
222
274
  - spec/report_spec.rb
223
275
  - spec/spec_helper.rb
224
276
  - spec/support/shared_contexts/rake.rb
225
277
  - spec/tasks/reparty_task_spec.rb
278
+ - spec/vcr_helper.rb
226
279
  homepage: https://github.com/timdorr/reparty
227
280
  licenses:
228
281
  - MIT
@@ -236,7 +289,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
236
289
  - !ruby/object:Gem::Version
237
290
  segments:
238
291
  - 0
239
- hash: 1402825386359699857
292
+ hash: 1855217469676328277
240
293
  version: '0'
241
294
  none: false
242
295
  required_rubygems_version: !ruby/object:Gem::Requirement
@@ -245,7 +298,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
245
298
  - !ruby/object:Gem::Version
246
299
  segments:
247
300
  - 0
248
- hash: 1402825386359699857
301
+ hash: 1855217469676328277
249
302
  version: '0'
250
303
  none: false
251
304
  requirements: []
@@ -255,10 +308,13 @@ signing_key:
255
308
  specification_version: 3
256
309
  summary: Stupid easy business analytics
257
310
  test_files:
311
+ - spec/cassettes/sendgrid.yml
258
312
  - spec/email_spec.rb
259
313
  - spec/reparty_spec.rb
260
314
  - spec/report/active_record_spec.rb
315
+ - spec/report/sendgrid_spec.rb
261
316
  - spec/report_spec.rb
262
317
  - spec/spec_helper.rb
263
318
  - spec/support/shared_contexts/rake.rb
264
319
  - spec/tasks/reparty_task_spec.rb
320
+ - spec/vcr_helper.rb