Module: Vanity::Source

Included in:
Backtweets, Github, GithubIssues, RubyGems
Defined in:
lib/vanity/source.rb,
lib/vanity/sources/github.rb,
lib/vanity/sources/ruby_gems.rb,
lib/vanity/sources/backtweets.rb,
lib/vanity/sources/github_issues.rb

Overview

Each collector is tuned to use a given source with a given set of parameters. For example, a metric (collector) of Twitter followers would use the Twitter source and parameter telling it which Twitter account to watch.

Setup

A collector is setup in four steps. First, the #display method returns an HTML form which will be displayed to the user. In fact, this method returns two values:

  • inputs – HTML input controls for setting up a new controller.

  • notes – Additional setup notes, e.g. other steps that need to be followed, what values to supply, etc.

Wrap input controls within the label and use the source notation for the name attribute. For example, for our Twitter source:

<label>Screen name <input type="text" name="source[screen_name]" size="30"></label>

When the form is filled, the #setup method is called with a context and values from the form fields. Since the source needs to store state information about the collector, it uses the context for that. The context is a Hash that can store basic Ruby values (nil, String, boolean, Numeric, Array and Hash).

In particular, #setup must set specific values for each collector:

  • metric.name – The name of the metric, e.g. Twitter source might pick the name “Twitter mentions of @vanitydash”.

  • metric.columns – Specifies the columns (at least one) that make up this metric. The value if an array where each item describes a single column, see below for more details.

  • metric.totals – True if this metric collects totals (life-time values, e.g. downloads, user accounts), false if it only collects daily values (e.g. average response time, number of instances in cluster).

For metric.columns, each item can use the following keys:

  • id – Column identifier (if missing, derived from column name)

  • name – Column name (required)

Shortly after #setup, the #validate method is called with the same context. If it raises any exception, the error is displayed to the user and the collector is discarded. Otherwise, #register is called with a Webhook URL. Some sources use that to register the Webhook with another service.

Updates

Periodically, the source will be asked to update the collector by calling the #update method. This method is called with the same context and a block. If the source service passes data through the web hook, then #update is called with context, Request object and a block.

The block passed to #update can be used to update the collector by yielding to it with a hash of named arguments. A single update may yield any number of times with any combination of arguments.

The named arguments are:

  • set – Columns to set (metric). Records the most recent value for this metric. This is a hash where the keys are column ids (or indexes), the values are integers or floats.

  • inc – Columns to increment (metric). Records a change in value which may be positive or negative. This is a hash where the keys are column ids (or indexes), the values are integers or floats.

  • timestamp – The Time (if missing, uses the current system time).

  • activity – Activity to show in the stream. See below.

Activity can specify the following attributes:

  • uid – Unique identifier (within the scope of this source). For example, if activity is a release, this could be the version number.

  • html – HTML contents of the activity.

  • text – Text contents of the activity (can be used instead of html).

  • url – URL for original resource (e.g. blog post, tweet).

  • tags – Any number of tags for filtering activities like this (e.g. twitter, mention). Tags are lowercased and can contain alphanumeric, dashes and underscore.

  • person – Person who performed this activity. A hash with the (all optional) values :name, :email, :url and :photo.

  • timestamp – Timestamp activity occurred.

HTML can contain links (HTTP/S and email), images, bold, italics, paragraphs, block quotes, lists, tables, pre-formatted text, video and a few other elements. Scripts, objects, styles are obviously not allowed.

Occasionally, the #meta method is called. This method is used to display meta-data from the most recent state (i.e. last update). It returns an array of fields, each being a hash with the following values:

  • title – Title for this field (not required)

  • text – Text to show as value of the field

  • url – Link (not required)

Teardown

Eventually the collector is destroyed and the Webhook is unregistered by calling #unregister.

Defined Under Namespace

Modules: ClassMethods Classes: Backtweets, Github, GithubIssues, RubyGems

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Class Attribute Details

.api_keysObject

API keys (see instance method api_key).



134
135
136
# File 'lib/vanity/source.rb', line 134

def api_keys
  @api_keys
end

.loggerObject

Returns the value of attribute logger.



106
107
108
# File 'lib/vanity/source.rb', line 106

def logger
  @logger
end

Class Method Details

.allObject

Returns all available sources.



109
110
111
# File 'lib/vanity/source.rb', line 109

def all
  @sources ||= {}
end

.find(id) ⇒ Object

Returns source by its identifier.



114
115
116
# File 'lib/vanity/source.rb', line 114

def find(id)
  all[id]
end

.included(klass) ⇒ Object



136
137
138
# File 'lib/vanity/source.rb', line 136

def included(klass)
  klass.extend ClassMethods
end

.load_sources(path = File.dirname(__FILE__) + "/sources") ⇒ Object

Loads all the sources from the given directory. The source identifier is derived from the filename (e.g. all/my_source.rb becomes “my_source”). The source class must map to the source identifier within the Source module, e.g. Vanity::Source::MySource).



122
123
124
125
126
127
128
129
130
131
# File 'lib/vanity/source.rb', line 122

def load_sources(path = File.dirname(__FILE__) + "/sources")
  Dir["#{path}/*.rb"].each do |file|
    id = File.basename(file, ".rb")
    fail "Source #{id} already loaded" if all[id]
    load file
    klass = Source.const_get(id.camelize)
    all[id] = klass.new
    logger.info "Loaded source #{id}: #{klass}"
  end
end

Instance Method Details

#descriptionObject

Returns additional information about this source.

A good description helps the user find this source and decide whether or not to use it.

Uses the resource ‘description’.



164
165
166
# File 'lib/vanity/source.rb', line 164

def description
  resources["description"]
end

#displayObject

This method returns a hash with two values:

  • inputs – HTML fragment for a setup form

  • notes – HTML fragment for setup notes

Uses the resources ‘inputs’ and ‘notes’.



173
174
175
# File 'lib/vanity/source.rb', line 173

def display
  { :inputs=>resources["inputs"], :notes=>resources["notes"] }
end

#meta(context) ⇒ Object

Returns meta-data to be displayed alongside any other data. This method should return an array of hashes, each with the keys title (optional), text and url (optional). Good meta-data provides timely and relevant information that is not available in the raw data.



209
210
211
# File 'lib/vanity/source.rb', line 209

def meta(context)
  []
end

#nameObject

Returns the display name for this source.

Uses the resource ‘name’, and fallbacks on the class name (e.g Source::OneUp becomes “One Up”).



154
155
156
# File 'lib/vanity/source.rb', line 154

def name
  resources["name"] || source_id.titleize
end

#register(context, url) ⇒ Object

Called to register a Webhook (for sources that need it)



190
191
# File 'lib/vanity/source.rb', line 190

def register(context, url)
end

#setup(context, params) ⇒ Object

Called to setup a new collector with parameters from the HTML form (see #display). If there are any missing values, report them when #validate is called.



180
181
# File 'lib/vanity/source.rb', line 180

def setup(context, params)
end

#unregister(context, url) ⇒ Object

Called to unregister a Webhook (for sources that don’t need it).



202
203
# File 'lib/vanity/source.rb', line 202

def unregister(context, url)
end

#update(context, request, &block) ⇒ Object

Called to update the collector. This method will be called periodically with a context and a block. When triggered by a Webhook, it will be called with context, Request and a block. It can yield to the block any number of times with any combination of the supported named arguments for updating the collector.



198
199
# File 'lib/vanity/source.rb', line 198

def update(context, request, &block)
end

#validate(context) ⇒ Object

Called to validate the collector. If there are any error, raise an exception. A good error message will help the user understand which value is missing or invalid and how to correct that.



186
187
# File 'lib/vanity/source.rb', line 186

def validate(context)
end