README.md
# Tricle [![Build Status]](https://travis-ci.org/afeld/tricle) [![Code Climate]](https://codeclimate.com/github/afeld/tricle) [![Gem Version]](http://badge.fury.io/rb/tricle)
Automated metrics reporting via email. It's datastore-agnostic, so you can query SQL, MongoDB, external APIs, etc. to generate the stats you need. Uses [sparkle](https://github.com/afeld/sparkle) for generating sparklines. Example implementations:
* [github.com/afeld/tricle-afeld](https://github.com/afeld/tricle-afeld) ([live demo](http://tricle.afeld.me/weekly_metrics))
![screenshot](screenshot.png)
## Installation
This gem can be used within an existing project (e.g. a Rails app), or standalone.
```ruby
# Gemfile
gem 'tricle'
# Rakefile
require 'your/tricle/subclasses'
require 'tricle/tasks'
# your/config/file.rb
# unless you already have ActionMailer set up
ActionMailer::Base.raise_delivery_errors = true
ActionMailer::Base.smtp_settings = {
# ...
}
# Optional: Override the start day of the reports (Rails >= 4.0.3 only)
# http://api.rubyonrails.org/classes/Date.html#method-i-beginning_of_week-3D
Date.beginning_of_week = :monday
```
See [the ActionMailer guide](http://guides.rubyonrails.org/action_mailer_basics.html#action-mailer-configuration) for configuration details. Finally, execute:
```bash
bundle
```
## Usage
### Metrics
For each metric you want to report, create a new subclass of `Tricle::Metric` that implements `#size_for_range` and `#total`:
```ruby
class MyMetric < Tricle::Metric
# Retrieve the value of this metric for the provided time period. Generally
# this will be the count/value added/removed. Not necessary if #items_for_range
# is defined.
#
# @param start_at [Time]
# @param end_at [Time] non-inclusive
# @return [Fixnum]
def size_for_range(start_at, end_at)
# ...
end
# Optional: Retrieve the cumulative value for this metric. If not defined,
# the total won't be displayed in the mailer.
#
# @return [Fixnum] the grand total
def total
# ...
end
# Optional: Only necessary if using `list` for this Metric within your Mailer.
#
# @param start_at [Time]
# @param end_at [Time] non-inclusive
# @return [Enumerator]
def items_for_range(start_at, end_at)
# ...
end
end
```
If you would like finer-grain optimization, the methods included from the [`Aggregation`](lib/tricle/arregation.rb) mixin can be overridden.
### ActiveRecord Metrics
You can inherit from [`Tricle::ActiveRecordMetric`](lib/tricle/active_record_metric.rb) for even easier setup. By default, Tricle looks for records with a `created_at` timestamp between the `start_at` and `end_at` times.
```ruby
# app/metrics/new_users.rb
class NewUsers < Tricle::ActiveRecordMetric
# Apply any default scopes you need
def items
User.where(deleted_at: nil)
end
end
```
You can also override the `time_column` method to split the time intervals based on that value. For example, to see records that have been updated:
```ruby
# app/metrics/new_users.rb
class NewUsers < Tricle::ActiveRecordMetric
def items
User.where(deleted_at: nil)
end
def time_column
'updated_at'
end
end
```
#### "Lower is better" metrics
By default, Tricle highlights numbers that increased in green, and those that decreased in red. If you have a metric where a *lower* number is considered better, you'll want to override the `#better` method so Tricle highlights your cells properly:
```ruby
class LowerIsBetterMetric < Tricle::Metric
def better
:lower
end
...
end
```
You can also return `:none`, and none of your cells for that metric will be highlighted green or red.
### Mailers
Mailers specify how a particular set of Metrics should be sent. You can define one or multiple, to send different metrics to different groups of people.
```ruby
class MyMailer < Tricle::Mailer
# accepts the same options as ActionMailer... see "Default Hash" at
# http://rubydoc.info/gems/actionmailer/ActionMailer/Base
default(
# ...
)
self.period = :day # options are :day, :week (default), and :month
metric MyMetric1
metric MyMetric2
# ...
# optional: metrics can be grouped
group "Group 1 Name" do
metric MyMetric3
# ...
end
group "Group 2 Name" do
metric MyMetric4
# ...
end
# optional: list the items for the specified Metric
list MyMetric2 do |item|
# return the HTML string for each particular item
end
# ...
end
```
e.g.
```ruby
# app/mailers/weekly_insights.rb
class WeeklyInsights < Tricle::Mailer
default(
to: ['theteam@mycompany.com', 'theboss@mycompany.com'],
from: 'noreply@mycompany.com'
)
metric NewUsers
list NewUsers do |user|
<<-MARKUP
<h3>#{user.name}</h3>
<div>#{user.location}</div>
<a href="mailto:#{user.email}>#{user.email}</a>
MARKUP
end
end
```
The subject line will be based on the Mailer class name.
#### Passing options to a Metric
Sometimes, you'll want to initialize a Metric with specific options. If you pass a hash as a second argument to the mailer's `metric` method, the Metric will be initialized with an `@options` instance variable.
```ruby
class IntelligenceBrief < Tricle::Mailer
metric NewUsers, matching_email: '@gmail.com'
# or for a list...
list NewUsers, matching_email: '@gmail.com' do |item|
...
end
end
```
### Previewing
Since you'd probably like to preview your mailers before sending them, set up the `Tricle::MailPreview` Rack app (which uses [MailView](https://github.com/37signals/mail_view)).
#### Within a Rails app
```ruby
# config/initializers/tricle.rb
require 'tricle/mail_preview'
# config/routes.rb
if Rails.env.development?
mount Tricle::MailPreview => 'mail_view'
end
```
and navigate to [localhost:3000/mail_view](http://localhost:3000/mail_view).
#### Standalone
```bash
bundle exec rake tricle:preview
open http://localhost:8080
```
### Global Configuration
To set global configuration options, in an initializer:
```ruby
Tricle.configure do |c|
c.sparklines = false # default: true
end
```
## Deploying
To send all Tricle emails, run
```bash
rake tricle:emails:send # sends all emails
```
or
```bash
rake tricle:emails:daily # sends emails with period = :day
```
To set a speficic time zone, use the `TZ` environment variable (see the list [here](http://en.wikipedia.org/wiki/List_of_tz_database_time_zones)).
```bash
TZ=UTC rake tricle:emails:send
```
### Heroku
1. Deploy the application.
* If this is a standalone app, you won't need a `web` process.
1. Enable an [add-on for email delivery](https://addons.heroku.com/?q=email%20deliver), and [configure](#installation) ActionMailer to send via that provider.
1. Enable [Heroku Scheduler](https://devcenter.heroku.com/articles/scheduler).
```bash
heroku addons:add scheduler:standard
heroku addons:open scheduler
```
1. Add a "job".
* For a report sent once per day, use the command from [Deploying](#deploying).
* For a report sent once per week, use `rake tricle:emails:send_after_beginning_of_week` daily.
* Heroku Scheduler only supports a maximum of daily tasks, hence needing to use a special task.
You can trigger the email(s) manually for testing with `heroku run rake tricle:emails:send`.
[Build Status]: http://img.shields.io/travis/afeld/tricle.svg?style=flat
[Gem Version]: http://img.shields.io/gem/v/tricle.svg?style=flat
[Code Climate]: http://img.shields.io/codeclimate/github/afeld/tricle.svg?style=flat