garb-reporter 0.0.1
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/.gitignore +6 -0
- data/.rspec +2 -0
- data/.rvmrc +1 -0
- data/Gemfile +4 -0
- data/README +1 -0
- data/Rakefile +1 -0
- data/config/vcr_setup.rb +7 -0
- data/garb-reporter.gemspec +33 -0
- data/lib/garb-reporter/version.rb +3 -0
- data/lib/report.rb +64 -0
- data/spec/garb_reporter_spec.rb +88 -0
- data/spec/spec_helper.rb +7 -0
- data/vcr_cassettes/garb_authentication.yml +38 -0
- data/vcr_cassettes/get_profile.yml +40 -0
- metadata +153 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm --create ruby-1.8.7-p352@garb-reporter
|
data/Gemfile
ADDED
data/README
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Welcome to garb-reporter!
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/config/vcr_setup.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "garb-reporter/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "garb-reporter"
|
7
|
+
s.version = GarbReporter::VERSION
|
8
|
+
s.authors = ["Stu Liston"]
|
9
|
+
s.email = ["stuart.liston@gmail.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{Provides a reporter class for Garb}
|
12
|
+
s.description = %q{GarbReporter removes the need in Garb to create a new class for every report by offering a querying api that dynamically creates the Garb classes for you in the background.}
|
13
|
+
|
14
|
+
# Only running dependency is Garb (and its dependencies)
|
15
|
+
s.add_dependency "garb", "0.9.1"
|
16
|
+
|
17
|
+
# Development dependencies:
|
18
|
+
s.add_development_dependency "rspec", ">= 2.7.0"
|
19
|
+
s.add_development_dependency "i18n"
|
20
|
+
s.add_development_dependency "vcr"
|
21
|
+
s.add_development_dependency "fakeweb"
|
22
|
+
|
23
|
+
s.rubyforge_project = "garb-reporter"
|
24
|
+
|
25
|
+
s.files = `git ls-files`.split("\n")
|
26
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
27
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
28
|
+
s.require_paths = ["lib"]
|
29
|
+
|
30
|
+
# specify any dependencies here; for example:
|
31
|
+
# s.add_development_dependency "rspec"
|
32
|
+
# s.add_runtime_dependency "rest-client"
|
33
|
+
end
|
data/lib/report.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
require "garb-reporter/version"
|
2
|
+
|
3
|
+
module GarbReporter
|
4
|
+
|
5
|
+
class Report
|
6
|
+
|
7
|
+
def initialize(profile)
|
8
|
+
@profile = profile
|
9
|
+
end
|
10
|
+
|
11
|
+
def method_missing(method, *args)
|
12
|
+
|
13
|
+
method_name = method.to_s
|
14
|
+
super unless valid_method_name?(method_name)
|
15
|
+
|
16
|
+
class_name = build_class_name(method_name)
|
17
|
+
klass = existing_report_class(class_name) || build_new_report_class(method_name, class_name)
|
18
|
+
klass.results(@profile)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def valid_method_name?(method_name)
|
24
|
+
(!method_name.empty? && method_name.scan('_by_').count <= 1 && !method_name.start_with?('_', 'by_', 'and_') && !method_name.end_with?('_', '_by', '_and'))
|
25
|
+
end
|
26
|
+
|
27
|
+
def existing_report_class(class_name)
|
28
|
+
class_exists?(class_name) ? GarbReporter.const_get(class_name) : nil
|
29
|
+
end
|
30
|
+
|
31
|
+
def class_exists?(class_name)
|
32
|
+
GarbReporter.const_defined?(class_name)
|
33
|
+
rescue NameError
|
34
|
+
return false
|
35
|
+
end
|
36
|
+
|
37
|
+
def build_new_report_class(method_name, class_name)
|
38
|
+
klass = GarbReporter.const_set(class_name, Class.new())
|
39
|
+
klass.extend Garb::Model
|
40
|
+
klass.metrics << extract_metrics(method_name)
|
41
|
+
klass.dimensions << extract_dimensions(method_name)
|
42
|
+
return klass
|
43
|
+
end
|
44
|
+
|
45
|
+
def build_class_name(method_name)
|
46
|
+
method_name.split('_').collect { |w| w.capitalize! }.join
|
47
|
+
end
|
48
|
+
|
49
|
+
def extract_metrics(method_name)
|
50
|
+
build_metrics_and_dimensions(method_name).first || []
|
51
|
+
end
|
52
|
+
|
53
|
+
def extract_dimensions(method_name)
|
54
|
+
return [] unless method_name.include?('_by_')
|
55
|
+
|
56
|
+
build_metrics_and_dimensions(method_name).last || []
|
57
|
+
end
|
58
|
+
|
59
|
+
def build_metrics_and_dimensions(method_name)
|
60
|
+
(metrics, dimensions) = method_name.split('_by_').collect { |part| part.split('_and_').collect(&:to_sym) }
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GarbReporter do
|
4
|
+
|
5
|
+
before do
|
6
|
+
|
7
|
+
# get VCR to serve us up a previously-canned http response for successful login
|
8
|
+
VCR.use_cassette('garb authentication') do
|
9
|
+
Garb::Session.login('stuart@example.com', 'password')
|
10
|
+
end
|
11
|
+
|
12
|
+
# get VCR to serve us up a previously-canned http response for fetching profiles
|
13
|
+
VCR.use_cassette('get profile') do
|
14
|
+
@profile = Garb::Management::Profile.all.detect { |p| p.web_property_id == 'UA-12345678-1' }
|
15
|
+
end
|
16
|
+
|
17
|
+
@report = GarbReporter::Report.new(@profile)
|
18
|
+
end
|
19
|
+
|
20
|
+
describe 'build_class_name' do
|
21
|
+
|
22
|
+
it 'should capitalise the string' do
|
23
|
+
@report.send(:build_class_name, 'visits').should == 'Visits'
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should strip out underscores' do
|
27
|
+
@report.send(:build_class_name, 'visits_by_office').should_not match(/_/)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should handle really long strings' do
|
31
|
+
@report.send(:build_class_name, 'visits_and_pageviews_and_clicks_by_date_and_office').should == 'VisitsAndPageviewsAndClicksByDateAndOffice'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe 'valid_method_name' do
|
36
|
+
|
37
|
+
it 'should not allow a blank string' do
|
38
|
+
@report.send(:valid_method_name?, '').should be_false
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should not allow more than one instance of "_by_"' do
|
42
|
+
@report.send(:valid_method_name?, 'visits_by_office_by_date').should be_false
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should not start or end with "_by_" or "_and_' do
|
46
|
+
@report.send(:valid_method_name?, '_by_date').should be_false
|
47
|
+
@report.send(:valid_method_name?, 'visits_by_').should be_false
|
48
|
+
@report.send(:valid_method_name?, '_and_date').should be_false
|
49
|
+
@report.send(:valid_method_name?, 'visits_and_').should be_false
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe 'extract_metrics' do
|
54
|
+
|
55
|
+
it 'should extract a single metric' do
|
56
|
+
@report.send(:extract_metrics, 'visits').should == [:visits]
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should extract multiple metrics' do
|
60
|
+
@report.send(:extract_metrics, 'visits_and_clicks_and_foo_and_bar').should == [:visits, :clicks, :foo, :bar]
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'should ignore a dimension' do
|
64
|
+
@report.send(:extract_metrics, 'visits_and_clicks_by_date').should == [:visits, :clicks]
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should ignore multiple dimensions' do
|
68
|
+
@report.send(:extract_metrics, 'visits_and_clicks_by_date_and_office').should == [:visits, :clicks]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe 'dimensions' do
|
73
|
+
|
74
|
+
it 'should know when there are no dimensions' do
|
75
|
+
@report.send(:extract_dimensions, 'visits').should == []
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'should extract a single dimension' do
|
79
|
+
@report.send(:extract_dimensions, 'visits_by_date').should == [:date]
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'should extract multiple dimensions' do
|
83
|
+
@report.send(:extract_dimensions, 'visits_by_date_and_office').should == [:date, :office]
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
---
|
2
|
+
- !ruby/struct:VCR::HTTPInteraction
|
3
|
+
request: !ruby/struct:VCR::Request
|
4
|
+
method: :post
|
5
|
+
uri: https://www.google.com:443/accounts/ClientLogin
|
6
|
+
body: Passwd=password&service=analytics&accountType=HOSTED_OR_GOOGLE&Email=stuart%40example.com&source=vigetLabs-garb-001
|
7
|
+
headers:
|
8
|
+
content-type:
|
9
|
+
- application/x-www-form-urlencoded
|
10
|
+
response: !ruby/struct:VCR::Response
|
11
|
+
status: !ruby/struct:VCR::ResponseStatus
|
12
|
+
code: 200
|
13
|
+
message: OK
|
14
|
+
headers:
|
15
|
+
x-content-type-options:
|
16
|
+
- nosniff
|
17
|
+
expires:
|
18
|
+
- Mon, 01-Jan-1990 00:00:00 GMT
|
19
|
+
content-type:
|
20
|
+
- text/plain
|
21
|
+
server:
|
22
|
+
- GSE
|
23
|
+
x-xss-protection:
|
24
|
+
- 1; mode=block
|
25
|
+
date:
|
26
|
+
- Wed, 30 Nov 2011 02:58:23 GMT
|
27
|
+
content-length:
|
28
|
+
- "881"
|
29
|
+
cache-control:
|
30
|
+
- no-cache, no-store
|
31
|
+
pragma:
|
32
|
+
- no-cache
|
33
|
+
body: |
|
34
|
+
SID=DQAAAMEAAABEPGo2a2ewm6JsKoF18TB1W4NzG21XMZZoX4uS44RP0BhBnP7daTnL3ZPtLO8fgEr-Ym-nF5OByN29mkdOSdFBA90zSMSlGedGyzryY_NC93C3zMFRe0Sa8ia-snWqbp7U_ja4u7v6mC7t4We_eyGRujR3tRJeCJURzYmcFLJtAuNPmkNWA8sZ1g-libvB6Y9Q_iSVyKWVU1te0vVBOamN1HPQizwDcNpEX4nKACiuHyt-Uj1fn1kTnS4HDbNirlQy2yjlt2klvnzy5GMPVkZN
|
35
|
+
LSID=DQAAAMIAAAB-o-KXnRZiasADsE59dnSkvovrXlY0htPFyvyeGZKIKumNGpatwtMVTogWlnGlRa0uZP4C3yyyOIXizXaogiYKlwKo3kEj7eo0QtnWjwXurwktNrfqUtdcoxjl8UkV_cIJl77aFcg5J5aQUJgv7d96jriTI5JB1W6krd3RjhqyjYICp5abqrMKASsUqjOaCBxI__5WvH4DYGQD4n64BrdCUUMFaGXOFDnpiPATWM9YvjQf7qDt0q_UkQify2tvlIJl70gvA-5dV-Ps1agz7Fpp
|
36
|
+
Auth=DQAAAMIAAAB-o-KXnRZiasADsE59dnSkvovrXlY0htPFyvyeGZKIKumNGpatwtMVTogWlnGlRa29p1ILfFYTDmueKnj9Ds2SOVu0tx670XjlgrRvtbia1MJ7p0M4uB5aJr4UMqqrkMF4dsnA28Les-plij6icPJq9OxCwQ2og_1q3bCjs-wkC6CN9lEBvQPeLj5ipIiCNM8fap03Qxfj7-0vTVFt4nP-kpYuIpILZja05N0am1_EAItaUOXWzcjPe_tDqSkXGN_5Mm46v7Qs2dR35ssEitsT
|
37
|
+
|
38
|
+
http_version: "1.1"
|
@@ -0,0 +1,40 @@
|
|
1
|
+
---
|
2
|
+
- !ruby/struct:VCR::HTTPInteraction
|
3
|
+
request: !ruby/struct:VCR::Request
|
4
|
+
method: :get
|
5
|
+
uri: https://www.google.com:443/analytics/feeds/datasources/ga/accounts/~all/webproperties/~all/profiles
|
6
|
+
body:
|
7
|
+
headers:
|
8
|
+
authorization:
|
9
|
+
- GoogleLogin auth=DQAAAMIAAAB-o-KXnRZiasADsE59dnSkvovrXlY0htPFyvyeGZKIKumNGpatwtMVTogWlnGlRa29p1ILfFYTDmueKnj9Ds2SOVu0tx670XjlgrRvtbia1MJ7p0M4uB5aJr4UMqqrkMF4dsnA28Les-plij6icPJq9OxCwQ2og_1q3bCjs-wkC6CN9lEBvQPeLj5ipIiCNM8fap03Qxfj7-0vTVFt4nP-kpYuIpILZja05N0am1_EAItaUOXWzcjPe_tDqSkXGN_5Mm46v7Qs2dR35ssEitsT
|
10
|
+
gdata-version:
|
11
|
+
- "2"
|
12
|
+
response: !ruby/struct:VCR::Response
|
13
|
+
status: !ruby/struct:VCR::ResponseStatus
|
14
|
+
code: 200
|
15
|
+
message: OK
|
16
|
+
headers:
|
17
|
+
x-frame-options:
|
18
|
+
- SAMEORIGIN
|
19
|
+
x-content-type-options:
|
20
|
+
- nosniff
|
21
|
+
last-modified:
|
22
|
+
- Wed, 30 Nov 2011 02:58:25 GMT
|
23
|
+
expires:
|
24
|
+
- Wed, 30 Nov 2011 02:58:25 GMT
|
25
|
+
content-type:
|
26
|
+
- application/atom+xml; charset=UTF-8; type=feed
|
27
|
+
server:
|
28
|
+
- GSE
|
29
|
+
x-xss-protection:
|
30
|
+
- 1; mode=block
|
31
|
+
date:
|
32
|
+
- Wed, 30 Nov 2011 02:58:25 GMT
|
33
|
+
gdata-version:
|
34
|
+
- "2.1"
|
35
|
+
vary:
|
36
|
+
- Accept, X-GData-Authorization, GData-Version
|
37
|
+
cache-control:
|
38
|
+
- private, max-age=0, must-revalidate, no-transform
|
39
|
+
body: <?xml version="1.0" encoding="UTF-8"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:dxp="http://schemas.google.com/analytics/2009" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:gd="http://schemas.google.com/g/2005" gd:kind="analytics#profiles"> <id>https://www.google.com/analytics/feeds/datasources/ga/accounts/~all/webproperties/~all/profiles</id> <updated>2011-11-30T02:58:25.381Z</updated> <title>Google Analytics Profiles for stuart@example.com</title> <link rel="self" type="application/atom+xml" href="https://www.google.com/analytics/feeds/datasources/ga/accounts/~all/webproperties/~all/profiles"/> <author> <name>Google Analytics</name> </author> <generator version="1.0">Google Analytics</generator> <openSearch:totalResults>53</openSearch:totalResults> <openSearch:startIndex>1</openSearch:startIndex> <openSearch:itemsPerPage>1000</openSearch:itemsPerPage> <entry gd:etag="W/"C0cHSXw7fSp7I2A9WhRREUw."" gd:kind="analytics#profile"> <id>https://www.google.com/analytics/feeds/datasources/ga/accounts/12345678/webproperties/UA-12345678-1/profiles/67976579</id> <updated>2011-11-23T21:03:58.205-08:00</updated> <title>Google Analytics Profile TEST</title> <link rel="self" type="application/atom+xml" href="https://www.google.com/analytics/feeds/datasources/ga/accounts/12345678/webproperties/UA-12345678-1/profiles/67976579"/> <link rel="http://schemas.google.com/ga/2009#parent" type="application/atom+xml" href="https://www.google.com/analytics/feeds/datasources/ga/accounts/12345678/webproperties/UA-12345678-1" gd:targetKind="analytics#webproperty"/> <link rel="http://schemas.google.com/ga/2009#child" type="application/atom+xml" href="https://www.google.com/analytics/feeds/datasources/ga/accounts/12345678/webproperties/UA-12345678-1/profiles/67976579/goals" gd:targetKind="analytics#goals"/> <dxp:property name="ga:accountId" value="12345678"/> <dxp:property name="ga:webPropertyId" value="UA-12345678-1"/> <dxp:property name="ga:profileName" value="CAV UAT"/> <dxp:property name="ga:profileId" value="67976579"/> <dxp:property name="dxp:tableId" value="ga:67976579"/> <dxp:property name="ga:currency" value="USD"/> <dxp:property name="ga:timezone" value="America/Los_Angeles"/> </entry></feed>
|
40
|
+
http_version: "1.1"
|
metadata
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: garb-reporter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Stu Liston
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-11-30 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: garb
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - "="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 57
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
- 9
|
32
|
+
- 1
|
33
|
+
version: 0.9.1
|
34
|
+
type: :runtime
|
35
|
+
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rspec
|
38
|
+
prerelease: false
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
hash: 19
|
45
|
+
segments:
|
46
|
+
- 2
|
47
|
+
- 7
|
48
|
+
- 0
|
49
|
+
version: 2.7.0
|
50
|
+
type: :development
|
51
|
+
version_requirements: *id002
|
52
|
+
- !ruby/object:Gem::Dependency
|
53
|
+
name: i18n
|
54
|
+
prerelease: false
|
55
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
hash: 3
|
61
|
+
segments:
|
62
|
+
- 0
|
63
|
+
version: "0"
|
64
|
+
type: :development
|
65
|
+
version_requirements: *id003
|
66
|
+
- !ruby/object:Gem::Dependency
|
67
|
+
name: vcr
|
68
|
+
prerelease: false
|
69
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
70
|
+
none: false
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
hash: 3
|
75
|
+
segments:
|
76
|
+
- 0
|
77
|
+
version: "0"
|
78
|
+
type: :development
|
79
|
+
version_requirements: *id004
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: fakeweb
|
82
|
+
prerelease: false
|
83
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
hash: 3
|
89
|
+
segments:
|
90
|
+
- 0
|
91
|
+
version: "0"
|
92
|
+
type: :development
|
93
|
+
version_requirements: *id005
|
94
|
+
description: GarbReporter removes the need in Garb to create a new class for every report by offering a querying api that dynamically creates the Garb classes for you in the background.
|
95
|
+
email:
|
96
|
+
- stuart.liston@gmail.com
|
97
|
+
executables: []
|
98
|
+
|
99
|
+
extensions: []
|
100
|
+
|
101
|
+
extra_rdoc_files: []
|
102
|
+
|
103
|
+
files:
|
104
|
+
- .gitignore
|
105
|
+
- .rspec
|
106
|
+
- .rvmrc
|
107
|
+
- Gemfile
|
108
|
+
- README
|
109
|
+
- Rakefile
|
110
|
+
- config/vcr_setup.rb
|
111
|
+
- garb-reporter.gemspec
|
112
|
+
- lib/garb-reporter/version.rb
|
113
|
+
- lib/report.rb
|
114
|
+
- spec/garb_reporter_spec.rb
|
115
|
+
- spec/spec_helper.rb
|
116
|
+
- vcr_cassettes/garb_authentication.yml
|
117
|
+
- vcr_cassettes/get_profile.yml
|
118
|
+
homepage: ""
|
119
|
+
licenses: []
|
120
|
+
|
121
|
+
post_install_message:
|
122
|
+
rdoc_options: []
|
123
|
+
|
124
|
+
require_paths:
|
125
|
+
- lib
|
126
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
127
|
+
none: false
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
hash: 3
|
132
|
+
segments:
|
133
|
+
- 0
|
134
|
+
version: "0"
|
135
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
136
|
+
none: false
|
137
|
+
requirements:
|
138
|
+
- - ">="
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
hash: 3
|
141
|
+
segments:
|
142
|
+
- 0
|
143
|
+
version: "0"
|
144
|
+
requirements: []
|
145
|
+
|
146
|
+
rubyforge_project: garb-reporter
|
147
|
+
rubygems_version: 1.8.10
|
148
|
+
signing_key:
|
149
|
+
specification_version: 3
|
150
|
+
summary: Provides a reporter class for Garb
|
151
|
+
test_files:
|
152
|
+
- spec/garb_reporter_spec.rb
|
153
|
+
- spec/spec_helper.rb
|