reparty 0.3.2 → 0.5.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.
- data/History.md +6 -0
- data/README.md +19 -7
- data/app/mailers/report_mailer.rb +14 -1
- data/app/views/report_mailer/_mixpanel_funnel.html.erb +33 -0
- data/app/views/report_mailer/daily.html.erb +5 -0
- data/app/views/report_mailer/weekly.html.erb +62 -0
- data/lib/reparty/config.rb +7 -2
- data/lib/reparty/email.rb +8 -0
- data/lib/reparty/report/active_record.rb +1 -1
- data/lib/reparty/report/mixpanel_funnel.rb +38 -0
- data/lib/reparty/report/sendgrid.rb +1 -1
- data/lib/reparty/report.rb +5 -2
- data/lib/reparty/version.rb +1 -1
- data/lib/reparty.rb +3 -1
- data/lib/tasks/reparty.rake +10 -0
- data/reparty.gemspec +1 -0
- data/spec/cassettes/mixpanel.yml +145 -0
- data/spec/reparty_spec.rb +15 -5
- data/spec/report/mixpanel_funnel_spec.rb +38 -0
- data/spec/report_spec.rb +9 -12
- data/spec/tasks/reparty_task_spec.rb +38 -0
- data/spec/vcr_helper.rb +4 -0
- metadata +27 -4
    
        data/History.md
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | @@ -3,18 +3,22 @@ | |
| 3 3 | 
             
            __A business analytics reporting party!__
         | 
| 4 4 |  | 
| 5 5 | 
             
            Although initially concentrating on a daily email report, Reparty intends to be an easy 
         | 
| 6 | 
            -
            tool for  | 
| 6 | 
            +
            tool for generating reports focused on business analytics about your app.
         | 
| 7 7 |  | 
| 8 | 
            -
             | 
| 8 | 
            +
            A modular design is used, so reporting on a variety of different data sources is possible.
         | 
| 9 | 
            +
            Custom modules can be created within your app. The currently bundled modules are:
         | 
| 9 10 |  | 
| 10 11 | 
             
            * ActiveRecord, including arbitrary sum/count columns
         | 
| 11 | 
            -
            *  | 
| 12 | 
            -
            *  | 
| 13 | 
            -
             | 
| 12 | 
            +
            * SendGrid
         | 
| 13 | 
            +
            * Mixpanel (just funnels for now)
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            Other modules will be added over time. This is in use in production at my company, SalesLoft,
         | 
| 16 | 
            +
            so focus will be on the modules that best suit our needs. Feel free to submit a pull request
         | 
| 17 | 
            +
            with any modules you have created.
         | 
| 14 18 |  | 
| 15 19 | 
             
            ## Configuration
         | 
| 16 20 |  | 
| 17 | 
            -
             | 
| 21 | 
            +
            You can configure Reparty in an initalizer using a config block:
         | 
| 18 22 |  | 
| 19 23 | 
             
                Reparty.config do |config|
         | 
| 20 24 | 
             
                  config.from = "test@test.com"
         | 
| @@ -23,10 +27,18 @@ Whilst not completely done, this is how you'll configure it for emailing a daily | |
| 23 27 | 
             
                  config.add_report Reparty::Report::ActiveRecord, "New User Signups", :user
         | 
| 24 28 | 
             
                end
         | 
| 25 29 |  | 
| 30 | 
            +
            Better documentation of Reparty and each individual module's configuration is coming. For now,
         | 
| 31 | 
            +
             you'll just have to read the code (sorry!). Check the test suite for examples.
         | 
| 32 | 
            +
             | 
| 26 33 | 
             
            ## Usage
         | 
| 27 34 |  | 
| 28 35 | 
             
            Generating an email is as simple as a rake task:
         | 
| 29 36 |  | 
| 30 37 | 
             
                rake reparty:email[someone@somewhere.com]
         | 
| 31 38 |  | 
| 32 | 
            -
            You can run this in a cron job or other scheduling system.
         | 
| 39 | 
            +
            You can run this in a cron job or other scheduling system. A weekly email is currently hacked
         | 
| 40 | 
            +
            in to the code, which you can run using it's separate rake task:
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                rake reparty:weekly_email[someone@somewhere.com]
         | 
| 43 | 
            +
             | 
| 44 | 
            +
            This will likely change in the future, so watch out when upgrading!
         | 
| @@ -2,7 +2,6 @@ ActionMailer::Base.view_paths = File.expand_path('../../views/', __FILE__) | |
| 2 2 |  | 
| 3 3 | 
             
            class ReportMailer < ActionMailer::Base
         | 
| 4 4 | 
             
              def daily(to)
         | 
| 5 | 
            -
             | 
| 6 5 | 
             
                @title = Reparty::Email.title
         | 
| 7 6 |  | 
| 8 7 | 
             
                @reports = Reparty::Email.reports
         | 
| @@ -15,4 +14,18 @@ class ReportMailer < ActionMailer::Base | |
| 15 14 | 
             
                    subject: Reparty::Email.subject
         | 
| 16 15 | 
             
                )
         | 
| 17 16 | 
             
              end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              def weekly(to)
         | 
| 19 | 
            +
                @title = Reparty::Email.weekly_title
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                @reports = Reparty::Email.weekly_reports
         | 
| 22 | 
            +
                @reports.each {|r| r.attach(attachments)}
         | 
| 23 | 
            +
                attachments.inline['spacer.gif'] = File.read(Reparty.root + 'app/assets/images/spacer.gif')
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                mail(
         | 
| 26 | 
            +
                    from: Reparty::Email.from,
         | 
| 27 | 
            +
                    to: to,
         | 
| 28 | 
            +
                    subject: Reparty::Email.subject
         | 
| 29 | 
            +
                )
         | 
| 30 | 
            +
              end
         | 
| 18 31 | 
             
            end
         | 
| @@ -0,0 +1,33 @@ | |
| 1 | 
            +
            <table width="100%" cellpadding="0" cellspacing="25" border="0">
         | 
| 2 | 
            +
              <tr>
         | 
| 3 | 
            +
                <td align="left">
         | 
| 4 | 
            +
                  <h3 style="margin:0"><%= report.title %></h3>
         | 
| 5 | 
            +
                </td>
         | 
| 6 | 
            +
              </tr>
         | 
| 7 | 
            +
              <tr>
         | 
| 8 | 
            +
                <td align="center">
         | 
| 9 | 
            +
                  <table class="data" cellpadding="5" cellspacing="0" border="0">
         | 
| 10 | 
            +
                  <% (report.funnel_data.first[1]["steps"].size+1).times.each do |i|  %>
         | 
| 11 | 
            +
                    <% if i == 0 %>
         | 
| 12 | 
            +
                      <thead><tr>
         | 
| 13 | 
            +
                        <th width="100"></th>
         | 
| 14 | 
            +
                        <% report.funnel_data.each do |data| %>
         | 
| 15 | 
            +
                          <th><%= Date.parse(data[0]).strftime("%b %-d") %></th>
         | 
| 16 | 
            +
                        <% end %>
         | 
| 17 | 
            +
                      </tr></thead>
         | 
| 18 | 
            +
                    <% else %>
         | 
| 19 | 
            +
                      <tr>
         | 
| 20 | 
            +
                      <% report.funnel_data.each_with_index do |data, j| %>
         | 
| 21 | 
            +
                         <% if j == 0 %><td class="first"><%= data[1]["steps"][i-1]["goal"] %></td><% end %>
         | 
| 22 | 
            +
                         <td>
         | 
| 23 | 
            +
                           <%= number_to_percentage data[1]["steps"][i-1]["step_conv_ratio"]*100, precision: 2 %>
         | 
| 24 | 
            +
                           (<%= data[1]["steps"][i-1]["count"] %>)
         | 
| 25 | 
            +
                         </td>
         | 
| 26 | 
            +
                      <% end %>
         | 
| 27 | 
            +
                      </tr>
         | 
| 28 | 
            +
                    <% end %>
         | 
| 29 | 
            +
                  <% end %>
         | 
| 30 | 
            +
                  </table>
         | 
| 31 | 
            +
                </td>
         | 
| 32 | 
            +
              </tr>
         | 
| 33 | 
            +
            </table>
         | 
| @@ -10,6 +10,11 @@ | |
| 10 10 | 
             
                .report h3 { margin: 0; color: #444444; font-size: 16px; line-height: 24px; }
         | 
| 11 11 | 
             
                .report ul { margin-top: 5px; margin-bottom: 0; list-style-type: square; }
         | 
| 12 12 | 
             
                .report ul li { color: #888888; font-size: 14px; line-height: 20px; }
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                .data thead tr { background-color: #eef5fc; }
         | 
| 15 | 
            +
                .data th { font-size: 14px; text-align: center; }
         | 
| 16 | 
            +
                .data td { font-size: 13px; text-align: center; }
         | 
| 17 | 
            +
                .data td.first { background-color: #ecedee; color: #666666; font-size: 11px; text-align: left; }
         | 
| 13 18 | 
             
              </style>
         | 
| 14 19 | 
             
            </head>
         | 
| 15 20 | 
             
            <body bgcolor="#eeeeee" topmargin="0" leftmargin="0" marginheight="0" marginwidth="0">
         | 
| @@ -0,0 +1,62 @@ | |
| 1 | 
            +
            <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
         | 
| 2 | 
            +
            <html lang="en">
         | 
| 3 | 
            +
            <head>
         | 
| 4 | 
            +
              <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
         | 
| 5 | 
            +
              <style type="text/css">
         | 
| 6 | 
            +
                body { margin: 0; padding: 0; background: #eeeeee; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; }
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                .title h1 { margin: 0; color: #999999; font-weight: normal; font-size: 25px; text-shadow: 0 1px 0 #ffffff; }
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                .report h3 { margin: 0; color: #444444; font-size: 16px; line-height: 24px; }
         | 
| 11 | 
            +
                .report ul { margin-top: 5px; margin-bottom: 0; list-style-type: square; }
         | 
| 12 | 
            +
                .report ul li { color: #888888; font-size: 14px; line-height: 20px; }
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                .data thead tr { background-color: #eef5fc; }
         | 
| 15 | 
            +
                .data th { font-size: 14px; text-align: center; }
         | 
| 16 | 
            +
                .data td { font-size: 13px; text-align: center; }
         | 
| 17 | 
            +
                .data td.first { background-color: #ecedee; color: #666666; font-size: 11px; text-align: left; }
         | 
| 18 | 
            +
              </style>
         | 
| 19 | 
            +
            </head>
         | 
| 20 | 
            +
            <body bgcolor="#eeeeee" topmargin="0" leftmargin="0" marginheight="0" marginwidth="0">
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            <table width="100%" cellpadding="0" cellspacing="0" border="0" bgcolor="#eeeeee">
         | 
| 23 | 
            +
            <tr>
         | 
| 24 | 
            +
              <td bgcolor="#eeeeee" width="100%">
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                <table width="600" cellpadding="0" cellspacing="0" border="0" align="center" class="main">
         | 
| 27 | 
            +
                  <tr><td><img border="0" src="<%= attachments["spacer.gif"].url %>" width="1" height="25"><br></td></tr>
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                  <tr>
         | 
| 30 | 
            +
                    <td width="600" class="title">
         | 
| 31 | 
            +
                      <h1><%= @title %></h1>
         | 
| 32 | 
            +
                    </td>
         | 
| 33 | 
            +
                  </tr>
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  <tr><td><img border="0" src="<%= attachments["spacer.gif"].url %>" width="1" height="25"><br></td></tr>
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  <% @reports.each do |report| -%>
         | 
| 38 | 
            +
                    <tr>
         | 
| 39 | 
            +
                      <td bgcolor="#ffffff">
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                        <table width="600" cellpadding="0" cellspacing="0" border="0" align="center">
         | 
| 42 | 
            +
                          <tr>
         | 
| 43 | 
            +
                            <td bgcolor="<%= report.color %>" nowrap><img border="0" src="<%= attachments["spacer.gif"].url %>" width="5" height="1"></td>
         | 
| 44 | 
            +
                            <td class="report">
         | 
| 45 | 
            +
                              <%= render partial: report.class.name.demodulize.underscore, locals:{report:report} %>
         | 
| 46 | 
            +
                            </td>
         | 
| 47 | 
            +
                          </tr>
         | 
| 48 | 
            +
                        </table>
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                      </td>
         | 
| 51 | 
            +
                    </tr>
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                    <tr><td><img border="0" src="<%= attachments["spacer.gif"].url %>" width="1" height="25"><br></td></tr>
         | 
| 54 | 
            +
                <% end -%>
         | 
| 55 | 
            +
                </table>
         | 
| 56 | 
            +
             | 
| 57 | 
            +
              </td>
         | 
| 58 | 
            +
            </tr>
         | 
| 59 | 
            +
            </table>
         | 
| 60 | 
            +
             | 
| 61 | 
            +
            </body>
         | 
| 62 | 
            +
            </html>
         | 
    
        data/lib/reparty/config.rb
    CHANGED
    
    | @@ -2,15 +2,20 @@ require "ostruct" | |
| 2 2 |  | 
| 3 3 | 
             
            module Reparty
         | 
| 4 4 | 
             
              class Config < ::OpenStruct
         | 
| 5 | 
            -
                attr_reader :reports
         | 
| 5 | 
            +
                attr_reader :reports, :weekly_reports
         | 
| 6 6 |  | 
| 7 7 | 
             
                def initialize
         | 
| 8 8 | 
             
                  @reports = []
         | 
| 9 | 
            +
                  @weekly_reports = []
         | 
| 9 10 | 
             
                  super
         | 
| 10 11 | 
             
                end
         | 
| 11 12 |  | 
| 12 13 | 
             
                def add_report(report, *args, &block)
         | 
| 13 | 
            -
                  @reports << report.new(*args, &block)
         | 
| 14 | 
            +
                  @reports << report.new(1, *args, &block)
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                def add_weekly_report(report, *args, &block)
         | 
| 18 | 
            +
                  @weekly_reports << report.new(7, *args, &block)
         | 
| 14 19 | 
             
                end
         | 
| 15 20 | 
             
              end
         | 
| 16 21 | 
             
            end
         | 
    
        data/lib/reparty/email.rb
    CHANGED
    
    | @@ -5,6 +5,10 @@ module Reparty | |
| 5 5 | 
             
                    Reparty.reports
         | 
| 6 6 | 
             
                  end
         | 
| 7 7 |  | 
| 8 | 
            +
                  def weekly_reports
         | 
| 9 | 
            +
                    Reparty.weekly_reports
         | 
| 10 | 
            +
                  end
         | 
| 11 | 
            +
             | 
| 8 12 | 
             
                  def from
         | 
| 9 13 | 
             
                    Reparty.configuration.from || 'nobody@nowhere.com'
         | 
| 10 14 | 
             
                  end
         | 
| @@ -16,6 +20,10 @@ module Reparty | |
| 16 20 | 
             
                  def title
         | 
| 17 21 | 
             
                    Reparty.configuration.title || 'Your Daily Report:'
         | 
| 18 22 | 
             
                  end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  def weekly_title
         | 
| 25 | 
            +
                    Reparty.configuration.weekly_title || 'Your Weekly Report:'
         | 
| 26 | 
            +
                  end
         | 
| 19 27 | 
             
                end
         | 
| 20 28 | 
             
              end
         | 
| 21 29 | 
             
            end
         | 
| @@ -0,0 +1,38 @@ | |
| 1 | 
            +
            require 'mixpanel_client'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Reparty
         | 
| 4 | 
            +
              class Report
         | 
| 5 | 
            +
                class MixpanelFunnel < Report
         | 
| 6 | 
            +
                  attr_reader :funnel_id, :api_key, :api_secret
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  def initialize(*args, &block)
         | 
| 9 | 
            +
                    super(args.shift, args.shift)
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                    @funnel_id = args.shift
         | 
| 12 | 
            +
                    @api_key = args.shift
         | 
| 13 | 
            +
                    @api_secret = args.shift
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                    @color = "#7548a2"
         | 
| 16 | 
            +
                  end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  def client
         | 
| 19 | 
            +
                    @client ||= Mixpanel::Client.new({api_key: api_key, api_secret: api_secret})
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  def funnel_data
         | 
| 23 | 
            +
                    from_date = (DateTime.now-(interval*7)).strftime("%Y-%m-%d")
         | 
| 24 | 
            +
                    to_date = (DateTime.now-1).strftime("%Y-%m-%d")
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                    @funnel_data ||= Hash[client.request(
         | 
| 27 | 
            +
                        "funnels",
         | 
| 28 | 
            +
                        {
         | 
| 29 | 
            +
                            funnel_id: funnel_id,
         | 
| 30 | 
            +
                            interval: interval,
         | 
| 31 | 
            +
                            from_date: from_date,
         | 
| 32 | 
            +
                            to_date: to_date
         | 
| 33 | 
            +
                        }
         | 
| 34 | 
            +
                    )["data"].sort.reverse]
         | 
| 35 | 
            +
                  end
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
              end
         | 
| 38 | 
            +
            end
         | 
    
        data/lib/reparty/report.rb
    CHANGED
    
    | @@ -2,11 +2,14 @@ require 'gruff' | |
| 2 2 |  | 
| 3 3 | 
             
            module Reparty
         | 
| 4 4 | 
             
              class Report
         | 
| 5 | 
            -
                attr_reader :title, :color
         | 
| 5 | 
            +
                attr_reader :interval, :title, :color
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                def initialize(interval, title)
         | 
| 8 | 
            +
                  @interval = interval
         | 
| 6 9 |  | 
| 7 | 
            -
                def initialize(title)
         | 
| 8 10 | 
             
                  raise "Report: title must be defined" if title.blank?
         | 
| 9 11 | 
             
                  @title = title
         | 
| 12 | 
            +
             | 
| 10 13 | 
             
                  @color = "#832701"
         | 
| 11 14 | 
             
                end
         | 
| 12 15 |  | 
    
        data/lib/reparty/version.rb
    CHANGED
    
    
    
        data/lib/reparty.rb
    CHANGED
    
    | @@ -6,6 +6,7 @@ require "reparty/email" | |
| 6 6 | 
             
            require "reparty/report"
         | 
| 7 7 | 
             
            require "reparty/report/active_record"
         | 
| 8 8 | 
             
            require "reparty/report/sendgrid"
         | 
| 9 | 
            +
            require "reparty/report/mixpanel_funnel"
         | 
| 9 10 |  | 
| 10 11 | 
             
            require "reparty/engine"
         | 
| 11 12 |  | 
| @@ -16,7 +17,7 @@ module Reparty | |
| 16 17 | 
             
                end
         | 
| 17 18 |  | 
| 18 19 | 
             
                attr_accessor :configuration
         | 
| 19 | 
            -
                attr_reader :reports
         | 
| 20 | 
            +
                attr_reader :reports, :weekly_reports
         | 
| 20 21 |  | 
| 21 22 | 
             
                def config
         | 
| 22 23 | 
             
                  self.configuration = Config.new
         | 
| @@ -24,6 +25,7 @@ module Reparty | |
| 24 25 | 
             
                  yield(configuration)
         | 
| 25 26 |  | 
| 26 27 | 
             
                  @reports = self.configuration.reports
         | 
| 28 | 
            +
                  @weekly_reports = self.configuration.weekly_reports
         | 
| 27 29 | 
             
                end
         | 
| 28 30 | 
             
              end
         | 
| 29 31 | 
             
            end
         | 
    
        data/lib/tasks/reparty.rake
    CHANGED
    
    | @@ -8,4 +8,14 @@ namespace :reparty do | |
| 8 8 |  | 
| 9 9 | 
             
                ReportMailer.daily(args.address).deliver
         | 
| 10 10 | 
             
              end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              desc 'Generate a weekly email to be sent'
         | 
| 13 | 
            +
              task :weekly_email, [:address] => :environment do |t,args|
         | 
| 14 | 
            +
                unless args.address
         | 
| 15 | 
            +
                  puts "Error: An address is required."
         | 
| 16 | 
            +
                  next
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                ReportMailer.weekly(args.address).deliver
         | 
| 20 | 
            +
              end
         | 
| 11 21 | 
             
            end
         | 
    
        data/reparty.gemspec
    CHANGED
    
    | @@ -25,6 +25,7 @@ Gem::Specification.new do |spec| | |
| 25 25 | 
             
              spec.add_dependency "gruff"
         | 
| 26 26 | 
             
              spec.add_dependency "roadie"
         | 
| 27 27 | 
             
              spec.add_dependency "httparty"
         | 
| 28 | 
            +
              spec.add_dependency "mixpanel_client"
         | 
| 28 29 |  | 
| 29 30 | 
             
              spec.add_development_dependency "bundler", "~> 1.3"
         | 
| 30 31 | 
             
              spec.add_development_dependency "rake"
         | 
| @@ -0,0 +1,145 @@ | |
| 1 | 
            +
            ---
         | 
| 2 | 
            +
            http_interactions:
         | 
| 3 | 
            +
            - request:
         | 
| 4 | 
            +
                method: get
         | 
| 5 | 
            +
                uri: https://mixpanel.com/api/2.0/funnels?api_key=<MIXPANEL_KEY>&expire=1371655510&format=json&from_date=2013-06-12&funnel_id=<MIXPANEL_FUNNEL>&interval=1&sig=822d5273993b8b06e71358246bfa2d6f&to_date=2013-06-18
         | 
| 6 | 
            +
                body:
         | 
| 7 | 
            +
                  encoding: US-ASCII
         | 
| 8 | 
            +
                  string: ''
         | 
| 9 | 
            +
                headers:
         | 
| 10 | 
            +
                  Accept:
         | 
| 11 | 
            +
                  - ! '*/*'
         | 
| 12 | 
            +
                  User-Agent:
         | 
| 13 | 
            +
                  - Ruby
         | 
| 14 | 
            +
              response:
         | 
| 15 | 
            +
                status:
         | 
| 16 | 
            +
                  code: 200
         | 
| 17 | 
            +
                  message: OK
         | 
| 18 | 
            +
                headers:
         | 
| 19 | 
            +
                  Server:
         | 
| 20 | 
            +
                  - nginx/1.1.19
         | 
| 21 | 
            +
                  Date:
         | 
| 22 | 
            +
                  - Wed, 19 Jun 2013 15:15:10 GMT
         | 
| 23 | 
            +
                  Content-Type:
         | 
| 24 | 
            +
                  - application/json
         | 
| 25 | 
            +
                  Content-Length:
         | 
| 26 | 
            +
                  - '3161'
         | 
| 27 | 
            +
                  Connection:
         | 
| 28 | 
            +
                  - keep-alive
         | 
| 29 | 
            +
                  Vary:
         | 
| 30 | 
            +
                  - Accept-Encoding
         | 
| 31 | 
            +
                  Cache-Control:
         | 
| 32 | 
            +
                  - no-cache, no-store
         | 
| 33 | 
            +
                body:
         | 
| 34 | 
            +
                  encoding: US-ASCII
         | 
| 35 | 
            +
                  string: ! '{"meta": {"dates": ["2013-06-12", "2013-06-13", "2013-06-14", "2013-06-15",
         | 
| 36 | 
            +
                    "2013-06-16", "2013-06-17", "2013-06-18"]}, "data": {"2013-06-17": {"steps":
         | 
| 37 | 
            +
                    [{"count": 848, "step_conv_ratio": 1, "goal": "Opened LinkedIn Email", "overall_conv_ratio":
         | 
| 38 | 
            +
                    1, "avg_time": null, "event": "Opened LinkedIn Email"}, {"count": 29, "step_conv_ratio":
         | 
| 39 | 
            +
                    0.03419811320754717, "goal": "Viewed JCA Stream", "overall_conv_ratio": 0.03419811320754717,
         | 
| 40 | 
            +
                    "avg_time": 25755, "event": "Viewed JCA Stream"}], "analysis": {"completion":
         | 
| 41 | 
            +
                    29, "starting_amount": 848, "steps": 2, "worst": 1}}, "2013-06-16": {"steps":
         | 
| 42 | 
            +
                    [{"count": 571, "step_conv_ratio": 1, "goal": "Opened LinkedIn Email", "overall_conv_ratio":
         | 
| 43 | 
            +
                    1, "avg_time": null, "event": "Opened LinkedIn Email"}, {"count": 14, "step_conv_ratio":
         | 
| 44 | 
            +
                    0.024518388791593695, "goal": "Viewed JCA Stream", "overall_conv_ratio": 0.024518388791593695,
         | 
| 45 | 
            +
                    "avg_time": 109055, "event": "Viewed JCA Stream"}], "analysis": {"completion":
         | 
| 46 | 
            +
                    14, "starting_amount": 571, "steps": 2, "worst": 1}}, "2013-06-15": {"steps":
         | 
| 47 | 
            +
                    [{"count": 776, "step_conv_ratio": 1, "goal": "Opened LinkedIn Email", "overall_conv_ratio":
         | 
| 48 | 
            +
                    1, "avg_time": null, "event": "Opened LinkedIn Email"}, {"count": 20, "step_conv_ratio":
         | 
| 49 | 
            +
                    0.02577319587628866, "goal": "Viewed JCA Stream", "overall_conv_ratio": 0.02577319587628866,
         | 
| 50 | 
            +
                    "avg_time": 195452, "event": "Viewed JCA Stream"}], "analysis": {"completion":
         | 
| 51 | 
            +
                    20, "starting_amount": 776, "steps": 2, "worst": 1}}, "2013-06-14": {"steps":
         | 
| 52 | 
            +
                    [{"count": 901, "step_conv_ratio": 1, "goal": "Opened LinkedIn Email", "overall_conv_ratio":
         | 
| 53 | 
            +
                    1, "avg_time": null, "event": "Opened LinkedIn Email"}, {"count": 35, "step_conv_ratio":
         | 
| 54 | 
            +
                    0.038845726970033294, "goal": "Viewed JCA Stream", "overall_conv_ratio": 0.038845726970033294,
         | 
| 55 | 
            +
                    "avg_time": 148191, "event": "Viewed JCA Stream"}], "analysis": {"completion":
         | 
| 56 | 
            +
                    35, "starting_amount": 901, "steps": 2, "worst": 1}}, "2013-06-13": {"steps":
         | 
| 57 | 
            +
                    [{"count": 959, "step_conv_ratio": 1, "goal": "Opened LinkedIn Email", "overall_conv_ratio":
         | 
| 58 | 
            +
                    1, "avg_time": null, "event": "Opened LinkedIn Email"}, {"count": 44, "step_conv_ratio":
         | 
| 59 | 
            +
                    0.045881126173096975, "goal": "Viewed JCA Stream", "overall_conv_ratio": 0.045881126173096975,
         | 
| 60 | 
            +
                    "avg_time": 197465, "event": "Viewed JCA Stream"}], "analysis": {"completion":
         | 
| 61 | 
            +
                    44, "starting_amount": 959, "steps": 2, "worst": 1}}, "2013-06-12": {"steps":
         | 
| 62 | 
            +
                    [{"count": 980, "step_conv_ratio": 1, "goal": "Opened LinkedIn Email", "overall_conv_ratio":
         | 
| 63 | 
            +
                    1, "avg_time": null, "event": "Opened LinkedIn Email"}, {"count": 41, "step_conv_ratio":
         | 
| 64 | 
            +
                    0.04183673469387755, "goal": "Viewed JCA Stream", "overall_conv_ratio": 0.04183673469387755,
         | 
| 65 | 
            +
                    "avg_time": 206732, "event": "Viewed JCA Stream"}], "analysis": {"completion":
         | 
| 66 | 
            +
                    41, "starting_amount": 980, "steps": 2, "worst": 1}}, "2013-06-18": {"steps":
         | 
| 67 | 
            +
                    [{"count": 1071, "step_conv_ratio": 1, "goal": "Opened LinkedIn Email", "overall_conv_ratio":
         | 
| 68 | 
            +
                    1, "avg_time": null, "event": "Opened LinkedIn Email"}, {"count": 23, "step_conv_ratio":
         | 
| 69 | 
            +
                    0.021475256769374416, "goal": "Viewed JCA Stream", "overall_conv_ratio": 0.021475256769374416,
         | 
| 70 | 
            +
                    "avg_time": 15241, "event": "Viewed JCA Stream"}], "analysis": {"completion":
         | 
| 71 | 
            +
                    23, "starting_amount": 1071, "steps": 2, "worst": 1}}}}'
         | 
| 72 | 
            +
                http_version: 
         | 
| 73 | 
            +
              recorded_at: Wed, 19 Jun 2013 15:15:10 GMT
         | 
| 74 | 
            +
            - request:
         | 
| 75 | 
            +
                method: get
         | 
| 76 | 
            +
                uri: https://mixpanel.com/api/2.0/funnels?api_key=<MIXPANEL_KEY>&expire=1371655958&format=json&from_date=2013-05-01&funnel_id=<MIXPANEL_FUNNEL>&interval=7&sig=1d9e9bb9e518724bd091831b21c80f61&to_date=2013-06-18
         | 
| 77 | 
            +
                body:
         | 
| 78 | 
            +
                  encoding: US-ASCII
         | 
| 79 | 
            +
                  string: ''
         | 
| 80 | 
            +
                headers:
         | 
| 81 | 
            +
                  Accept:
         | 
| 82 | 
            +
                  - ! '*/*'
         | 
| 83 | 
            +
                  User-Agent:
         | 
| 84 | 
            +
                  - Ruby
         | 
| 85 | 
            +
              response:
         | 
| 86 | 
            +
                status:
         | 
| 87 | 
            +
                  code: 200
         | 
| 88 | 
            +
                  message: OK
         | 
| 89 | 
            +
                headers:
         | 
| 90 | 
            +
                  Server:
         | 
| 91 | 
            +
                  - nginx/1.1.19
         | 
| 92 | 
            +
                  Date:
         | 
| 93 | 
            +
                  - Wed, 19 Jun 2013 15:22:39 GMT
         | 
| 94 | 
            +
                  Content-Type:
         | 
| 95 | 
            +
                  - application/json
         | 
| 96 | 
            +
                  Content-Length:
         | 
| 97 | 
            +
                  - '2939'
         | 
| 98 | 
            +
                  Connection:
         | 
| 99 | 
            +
                  - keep-alive
         | 
| 100 | 
            +
                  Vary:
         | 
| 101 | 
            +
                  - Accept-Encoding
         | 
| 102 | 
            +
                  Cache-Control:
         | 
| 103 | 
            +
                  - no-cache, no-store
         | 
| 104 | 
            +
                body:
         | 
| 105 | 
            +
                  encoding: US-ASCII
         | 
| 106 | 
            +
                  string: ! '{"meta": {"dates": ["2013-05-01", "2013-05-08", "2013-05-15", "2013-05-22",
         | 
| 107 | 
            +
                    "2013-05-29", "2013-06-05", "2013-06-12"]}, "data": {"2013-05-15": {"steps":
         | 
| 108 | 
            +
                    [{"count": 0, "step_conv_ratio": 1, "goal": "Opened LinkedIn Email", "overall_conv_ratio":
         | 
| 109 | 
            +
                    1, "avg_time": null, "event": "Opened LinkedIn Email"}, {"count": 0, "step_conv_ratio":
         | 
| 110 | 
            +
                    0, "goal": "Viewed JCA Stream", "overall_conv_ratio": 0, "avg_time": null,
         | 
| 111 | 
            +
                    "event": "Viewed JCA Stream"}], "analysis": {"completion": 0, "starting_amount":
         | 
| 112 | 
            +
                    0, "steps": 2, "worst": 1}}, "2013-05-01": {"steps": [{"count": 0, "step_conv_ratio":
         | 
| 113 | 
            +
                    1, "goal": "Opened LinkedIn Email", "overall_conv_ratio": 1, "avg_time": null,
         | 
| 114 | 
            +
                    "event": "Opened LinkedIn Email"}, {"count": 0, "step_conv_ratio": 0, "goal":
         | 
| 115 | 
            +
                    "Viewed JCA Stream", "overall_conv_ratio": 0, "avg_time": null, "event": "Viewed
         | 
| 116 | 
            +
                    JCA Stream"}], "analysis": {"completion": 0, "starting_amount": 0, "steps":
         | 
| 117 | 
            +
                    2, "worst": 1}}, "2013-06-12": {"steps": [{"count": 1842, "step_conv_ratio":
         | 
| 118 | 
            +
                    1, "goal": "Opened LinkedIn Email", "overall_conv_ratio": 1, "avg_time": null,
         | 
| 119 | 
            +
                    "event": "Opened LinkedIn Email"}, {"count": 77, "step_conv_ratio": 0.041802388707926165,
         | 
| 120 | 
            +
                    "goal": "Viewed JCA Stream", "overall_conv_ratio": 0.041802388707926165, "avg_time":
         | 
| 121 | 
            +
                    131583, "event": "Viewed JCA Stream"}], "analysis": {"completion": 77, "starting_amount":
         | 
| 122 | 
            +
                    1842, "steps": 2, "worst": 1}}, "2013-05-08": {"steps": [{"count": 0, "step_conv_ratio":
         | 
| 123 | 
            +
                    1, "goal": "Opened LinkedIn Email", "overall_conv_ratio": 1, "avg_time": null,
         | 
| 124 | 
            +
                    "event": "Opened LinkedIn Email"}, {"count": 0, "step_conv_ratio": 0, "goal":
         | 
| 125 | 
            +
                    "Viewed JCA Stream", "overall_conv_ratio": 0, "avg_time": null, "event": "Viewed
         | 
| 126 | 
            +
                    JCA Stream"}], "analysis": {"completion": 0, "starting_amount": 0, "steps":
         | 
| 127 | 
            +
                    2, "worst": 1}}, "2013-05-29": {"steps": [{"count": 0, "step_conv_ratio":
         | 
| 128 | 
            +
                    1, "goal": "Opened LinkedIn Email", "overall_conv_ratio": 1, "avg_time": null,
         | 
| 129 | 
            +
                    "event": "Opened LinkedIn Email"}, {"count": 0, "step_conv_ratio": 0, "goal":
         | 
| 130 | 
            +
                    "Viewed JCA Stream", "overall_conv_ratio": 0, "avg_time": null, "event": "Viewed
         | 
| 131 | 
            +
                    JCA Stream"}], "analysis": {"completion": 0, "starting_amount": 0, "steps":
         | 
| 132 | 
            +
                    2, "worst": 1}}, "2013-05-22": {"steps": [{"count": 0, "step_conv_ratio":
         | 
| 133 | 
            +
                    1, "goal": "Opened LinkedIn Email", "overall_conv_ratio": 1, "avg_time": null,
         | 
| 134 | 
            +
                    "event": "Opened LinkedIn Email"}, {"count": 0, "step_conv_ratio": 0, "goal":
         | 
| 135 | 
            +
                    "Viewed JCA Stream", "overall_conv_ratio": 0, "avg_time": null, "event": "Viewed
         | 
| 136 | 
            +
                    JCA Stream"}], "analysis": {"completion": 0, "starting_amount": 0, "steps":
         | 
| 137 | 
            +
                    2, "worst": 1}}, "2013-06-05": {"steps": [{"count": 1588, "step_conv_ratio":
         | 
| 138 | 
            +
                    1, "goal": "Opened LinkedIn Email", "overall_conv_ratio": 1, "avg_time": null,
         | 
| 139 | 
            +
                    "event": "Opened LinkedIn Email"}, {"count": 82, "step_conv_ratio": 0.05163727959697733,
         | 
| 140 | 
            +
                    "goal": "Viewed JCA Stream", "overall_conv_ratio": 0.05163727959697733, "avg_time":
         | 
| 141 | 
            +
                    415671, "event": "Viewed JCA Stream"}], "analysis": {"completion": 82, "starting_amount":
         | 
| 142 | 
            +
                    1588, "steps": 2, "worst": 1}}}}'
         | 
| 143 | 
            +
                http_version: 
         | 
| 144 | 
            +
              recorded_at: Wed, 19 Jun 2013 15:22:39 GMT
         | 
| 145 | 
            +
            recorded_with: VCR 2.4.0
         | 
    
        data/spec/reparty_spec.rb
    CHANGED
    
    | @@ -12,11 +12,21 @@ describe Reparty do | |
| 12 12 | 
             
                Reparty.configuration.sender.should == "test@test.com"
         | 
| 13 13 | 
             
              end
         | 
| 14 14 |  | 
| 15 | 
            -
               | 
| 16 | 
            -
                 | 
| 17 | 
            -
                  config | 
| 15 | 
            +
              describe "adds reports" do
         | 
| 16 | 
            +
                subject do
         | 
| 17 | 
            +
                  Reparty.config do |config|
         | 
| 18 | 
            +
                    config.add_report Reparty::Report, "Some Report"
         | 
| 19 | 
            +
                    config.add_weekly_report Reparty::Report, "Some Weekly Report"
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
                  Reparty
         | 
| 18 22 | 
             
                end
         | 
| 19 | 
            -
             | 
| 20 | 
            -
                 | 
| 23 | 
            +
             | 
| 24 | 
            +
                its("reports.first")       { should be_kind_of(Reparty::Report) }
         | 
| 25 | 
            +
                its("reports.first.title") { should == "Some Report" }
         | 
| 26 | 
            +
                its("reports.size")        { should == 1 }
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                its("weekly_reports.first")       { should be_kind_of(Reparty::Report) }
         | 
| 29 | 
            +
                its("weekly_reports.first.title") { should == "Some Weekly Report" }
         | 
| 30 | 
            +
                its("weekly_reports.size")        { should == 1 }
         | 
| 21 31 | 
             
              end
         | 
| 22 32 | 
             
            end
         | 
| @@ -0,0 +1,38 @@ | |
| 1 | 
            +
            require_relative '../spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            interval_matcher = lambda do |request_made, request_stored|
         | 
| 4 | 
            +
              CGI.parse(URI(request_made.uri).query).fetch("interval",nil) == CGI.parse(URI(request_stored.uri).query).fetch("interval",nil)
         | 
| 5 | 
            +
            end
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            describe Reparty::Report::MixpanelFunnel, vcr: { cassette_name: "mixpanel", match_requests_on: [:method, :host, :path, interval_matcher] } do
         | 
| 8 | 
            +
              let(:funnel_id)       { ENV.fetch("MIXPANEL_FUNNEL", 123456) }
         | 
| 9 | 
            +
              let(:mixpanel_key)    { ENV.fetch("MIXPANEL_KEY",    "abc123") }
         | 
| 10 | 
            +
              let(:mixpanel_secret) { ENV.fetch("MIXPANEL_SECRET", "cba321") }
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              subject do
         | 
| 13 | 
            +
                Reparty.config do |config|
         | 
| 14 | 
            +
                  config.add_report Reparty::Report::MixpanelFunnel, "Mixpanel Funnel", funnel_id, mixpanel_key, mixpanel_secret
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
                Reparty.reports.last
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
              it { should be_kind_of(Reparty::Report::MixpanelFunnel) }
         | 
| 20 | 
            +
              its(:funnel_id)  { should == funnel_id }
         | 
| 21 | 
            +
              its(:api_key)    { should == mixpanel_key }
         | 
| 22 | 
            +
              its(:api_secret) { should == mixpanel_secret }
         | 
| 23 | 
            +
              its(:color)      { should == "#7548a2" }
         | 
| 24 | 
            +
              its(:client)     { should be_kind_of(Mixpanel::Client)}
         | 
| 25 | 
            +
             | 
| 26 | 
            +
              its("funnel_data.size") { should == 7 }
         | 
| 27 | 
            +
             | 
| 28 | 
            +
              describe "weekly interval" do
         | 
| 29 | 
            +
                subject do
         | 
| 30 | 
            +
                  Reparty.config do |config|
         | 
| 31 | 
            +
                    config.add_weekly_report Reparty::Report::MixpanelFunnel, "Mixpanel Funnel", funnel_id, mixpanel_key, mixpanel_secret
         | 
| 32 | 
            +
                  end
         | 
| 33 | 
            +
                  Reparty.weekly_reports.last
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                its("funnel_data.size") { should == 7 }
         | 
| 37 | 
            +
              end
         | 
| 38 | 
            +
            end
         | 
    
        data/spec/report_spec.rb
    CHANGED
    
    | @@ -1,27 +1,24 @@ | |
| 1 1 | 
             
            require 'spec_helper'
         | 
| 2 2 |  | 
| 3 3 | 
             
            describe Reparty::Report do
         | 
| 4 | 
            -
               | 
| 4 | 
            +
              let(:interval) { 1 }
         | 
| 5 | 
            +
              let(:title) { "title" }
         | 
| 5 6 |  | 
| 6 | 
            -
               | 
| 7 | 
            +
              subject { Reparty::Report.new(interval, title) }
         | 
| 7 8 |  | 
| 8 | 
            -
               | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
                }.to_not raise_exception
         | 
| 12 | 
            -
             | 
| 13 | 
            -
                expect {
         | 
| 14 | 
            -
                  Reparty::Report.new(nil)
         | 
| 15 | 
            -
                }.to raise_exception
         | 
| 9 | 
            +
              its(:color)    { should == "#832701"}
         | 
| 10 | 
            +
              its(:interval) { should == interval}
         | 
| 11 | 
            +
              its(:title)    { should == title}
         | 
| 16 12 |  | 
| 13 | 
            +
              it "requires a title" do
         | 
| 17 14 | 
             
                expect {
         | 
| 18 | 
            -
                  Reparty::Report.new("")
         | 
| 15 | 
            +
                  Reparty::Report.new(interval, "")
         | 
| 19 16 | 
             
                }.to raise_exception
         | 
| 20 17 | 
             
              end
         | 
| 21 18 |  | 
| 22 19 | 
             
              it "has an attach method" do
         | 
| 23 20 | 
             
                expect {
         | 
| 24 | 
            -
                   | 
| 21 | 
            +
                  subject.attach(nil)
         | 
| 25 22 | 
             
                }.to_not raise_exception
         | 
| 26 23 | 
             
              end
         | 
| 27 24 | 
             
            end
         | 
| @@ -42,10 +42,48 @@ describe "reparty:email" do | |
| 42 42 | 
             
                ].each{|u| User.create!(u) }
         | 
| 43 43 |  | 
| 44 44 | 
             
                Reparty.config do |config|
         | 
| 45 | 
            +
                  config.add_report Reparty::Report::MixpanelFunnel, "Mixpanel Funnel", ENV["MIXPANEL_FUNNEL"], ENV["MIXPANEL_KEY"], ENV["MIXPANEL_SECRET"]
         | 
| 45 46 | 
             
                  config.add_report Reparty::Report::ActiveRecord, "New User Signups", :user
         | 
| 46 47 | 
             
                  config.add_report Reparty::Report::Sendgrid, "Sendgrid Emails", ENV["SENDGRID_USER"], ENV["SENDGRID_PASSWORD"]
         | 
| 47 48 | 
             
                end
         | 
| 48 49 |  | 
| 50 | 
            +
                subject.invoke("test@test.com")
         | 
| 51 | 
            +
              end
         | 
| 52 | 
            +
            end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
            describe "reparty:weekly_email" do
         | 
| 55 | 
            +
              include_context "rake"
         | 
| 56 | 
            +
             | 
| 57 | 
            +
              before(:each) do
         | 
| 58 | 
            +
                User.delete_all
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                Reparty.config do |config|
         | 
| 61 | 
            +
                  config.add_weekly_report Reparty::Report::ActiveRecord, "New User Signups", :user
         | 
| 62 | 
            +
                end
         | 
| 63 | 
            +
              end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
              its(:prerequisites) { should include("environment") }
         | 
| 66 | 
            +
             | 
| 67 | 
            +
              it "requires an address" do
         | 
| 68 | 
            +
                STDOUT.should_receive(:puts)
         | 
| 69 | 
            +
                subject.invoke
         | 
| 70 | 
            +
              end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
              it "should generate an email" do
         | 
| 73 | 
            +
                expect{
         | 
| 74 | 
            +
                  subject.invoke("test@test.com")
         | 
| 75 | 
            +
                }.to change(ActionMailer::Base, :deliveries)
         | 
| 76 | 
            +
              end
         | 
| 77 | 
            +
             | 
| 78 | 
            +
              it "should send out via letter_opener", letteropener: true do
         | 
| 79 | 
            +
                require 'letter_opener'
         | 
| 80 | 
            +
                ActionMailer::Base.add_delivery_method :letter_opener, LetterOpener::DeliveryMethod, :location => File.expand_path('../../../tmp/letter_opener', __FILE__)
         | 
| 81 | 
            +
                ActionMailer::Base.delivery_method = :letter_opener
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                Reparty.config do |config|
         | 
| 84 | 
            +
                  config.add_weekly_report Reparty::Report::MixpanelFunnel, "Mixpanel Funnel", ENV["MIXPANEL_FUNNEL"], ENV["MIXPANEL_KEY"], ENV["MIXPANEL_SECRET"]
         | 
| 85 | 
            +
                end
         | 
| 86 | 
            +
             | 
| 49 87 | 
             
                subject.invoke("test@test.com")
         | 
| 50 88 | 
             
              end
         | 
| 51 89 | 
             
            end
         | 
    
        data/spec/vcr_helper.rb
    CHANGED
    
    | @@ -10,4 +10,8 @@ VCR.configure do |c| | |
| 10 10 |  | 
| 11 11 | 
             
              c.filter_sensitive_data("<SENDGRID_USER>")     { ENV.fetch("SENDGRID_USER","admin@someplace.com") }
         | 
| 12 12 | 
             
              c.filter_sensitive_data("<SENDGRID_PASSWORD>") { ENV.fetch("SENDGRID_PASSWORD","asdfasdf") }
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              c.filter_sensitive_data("<MIXPANEL_FUNNEL>") { ENV.fetch("MIXPANEL_FUNNEL",123456) }
         | 
| 15 | 
            +
              c.filter_sensitive_data("<MIXPANEL_KEY>")    { ENV.fetch("MIXPANEL_KEY","abc123") }
         | 
| 16 | 
            +
              c.filter_sensitive_data("<MIXPANEL_SECRET>") { ENV.fetch("MIXPANEL_SECRET","cba321") }
         | 
| 13 17 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -2,14 +2,14 @@ | |
| 2 2 | 
             
            name: reparty
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 4 | 
             
              prerelease: 
         | 
| 5 | 
            -
              version: 0. | 
| 5 | 
            +
              version: 0.5.0
         | 
| 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- | 
| 12 | 
            +
            date: 2013-06-19 00:00:00.000000000 Z
         | 
| 13 13 | 
             
            dependencies:
         | 
| 14 14 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 15 15 | 
             
              name: railties
         | 
| @@ -123,6 +123,22 @@ dependencies: | |
| 123 123 | 
             
                    version: '0'
         | 
| 124 124 | 
             
                none: false
         | 
| 125 125 | 
             
              prerelease: false
         | 
| 126 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 127 | 
            +
              name: mixpanel_client
         | 
| 128 | 
            +
              type: :runtime
         | 
| 129 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 130 | 
            +
                requirements:
         | 
| 131 | 
            +
                - - ! '>='
         | 
| 132 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 133 | 
            +
                    version: '0'
         | 
| 134 | 
            +
                none: false
         | 
| 135 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 136 | 
            +
                requirements:
         | 
| 137 | 
            +
                - - ! '>='
         | 
| 138 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 139 | 
            +
                    version: '0'
         | 
| 140 | 
            +
                none: false
         | 
| 141 | 
            +
              prerelease: false
         | 
| 126 142 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 127 143 | 
             
              name: bundler
         | 
| 128 144 | 
             
              type: :development
         | 
| @@ -254,22 +270,27 @@ files: | |
| 254 270 | 
             
            - app/assets/images/spacer.gif
         | 
| 255 271 | 
             
            - app/mailers/report_mailer.rb
         | 
| 256 272 | 
             
            - app/views/report_mailer/_active_record.html.erb
         | 
| 273 | 
            +
            - app/views/report_mailer/_mixpanel_funnel.html.erb
         | 
| 257 274 | 
             
            - app/views/report_mailer/_sendgrid.html.erb
         | 
| 258 275 | 
             
            - app/views/report_mailer/daily.html.erb
         | 
| 276 | 
            +
            - app/views/report_mailer/weekly.html.erb
         | 
| 259 277 | 
             
            - lib/reparty.rb
         | 
| 260 278 | 
             
            - lib/reparty/config.rb
         | 
| 261 279 | 
             
            - lib/reparty/email.rb
         | 
| 262 280 | 
             
            - lib/reparty/engine.rb
         | 
| 263 281 | 
             
            - lib/reparty/report.rb
         | 
| 264 282 | 
             
            - lib/reparty/report/active_record.rb
         | 
| 283 | 
            +
            - lib/reparty/report/mixpanel_funnel.rb
         | 
| 265 284 | 
             
            - lib/reparty/report/sendgrid.rb
         | 
| 266 285 | 
             
            - lib/reparty/version.rb
         | 
| 267 286 | 
             
            - lib/tasks/reparty.rake
         | 
| 268 287 | 
             
            - reparty.gemspec
         | 
| 288 | 
            +
            - spec/cassettes/mixpanel.yml
         | 
| 269 289 | 
             
            - spec/cassettes/sendgrid.yml
         | 
| 270 290 | 
             
            - spec/email_spec.rb
         | 
| 271 291 | 
             
            - spec/reparty_spec.rb
         | 
| 272 292 | 
             
            - spec/report/active_record_spec.rb
         | 
| 293 | 
            +
            - spec/report/mixpanel_funnel_spec.rb
         | 
| 273 294 | 
             
            - spec/report/sendgrid_spec.rb
         | 
| 274 295 | 
             
            - spec/report_spec.rb
         | 
| 275 296 | 
             
            - spec/spec_helper.rb
         | 
| @@ -289,7 +310,7 @@ required_ruby_version: !ruby/object:Gem::Requirement | |
| 289 310 | 
             
                - !ruby/object:Gem::Version
         | 
| 290 311 | 
             
                  segments:
         | 
| 291 312 | 
             
                  - 0
         | 
| 292 | 
            -
                  hash:  | 
| 313 | 
            +
                  hash: 1358861647946779491
         | 
| 293 314 | 
             
                  version: '0'
         | 
| 294 315 | 
             
              none: false
         | 
| 295 316 | 
             
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| @@ -298,7 +319,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 298 319 | 
             
                - !ruby/object:Gem::Version
         | 
| 299 320 | 
             
                  segments:
         | 
| 300 321 | 
             
                  - 0
         | 
| 301 | 
            -
                  hash:  | 
| 322 | 
            +
                  hash: 1358861647946779491
         | 
| 302 323 | 
             
                  version: '0'
         | 
| 303 324 | 
             
              none: false
         | 
| 304 325 | 
             
            requirements: []
         | 
| @@ -308,10 +329,12 @@ signing_key: | |
| 308 329 | 
             
            specification_version: 3
         | 
| 309 330 | 
             
            summary: Stupid easy business analytics
         | 
| 310 331 | 
             
            test_files:
         | 
| 332 | 
            +
            - spec/cassettes/mixpanel.yml
         | 
| 311 333 | 
             
            - spec/cassettes/sendgrid.yml
         | 
| 312 334 | 
             
            - spec/email_spec.rb
         | 
| 313 335 | 
             
            - spec/reparty_spec.rb
         | 
| 314 336 | 
             
            - spec/report/active_record_spec.rb
         | 
| 337 | 
            +
            - spec/report/mixpanel_funnel_spec.rb
         | 
| 315 338 | 
             
            - spec/report/sendgrid_spec.rb
         | 
| 316 339 | 
             
            - spec/report_spec.rb
         | 
| 317 340 | 
             
            - spec/spec_helper.rb
         |