garb-reporter 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/README.md +130 -0
- data/lib/garb-reporter.rb +2 -2
- data/lib/garb-reporter/version.rb +1 -1
- data/spec/garb_reporter_spec.rb +43 -1
- data/spec/spec_helper.rb +1 -1
- metadata +8 -8
- data/README +0 -1
- data/vcr_cassettes/garb_authentication.yml +0 -38
- data/vcr_cassettes/get_profile.yml +0 -40
data/.gitignore
CHANGED
data/README.md
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
Garb-Reporter
|
2
|
+
-------------
|
3
|
+
|
4
|
+
https://github.com/stuliston/garb-reporter
|
5
|
+
|
6
|
+
Description
|
7
|
+
-----------
|
8
|
+
|
9
|
+
Small wrapper to compliment the excellent Garb gem (http://github.com/vigetlabs/garb). Please have a glance over their documentation as it covers some imprtant Google Analytics stuff too.
|
10
|
+
|
11
|
+
Background
|
12
|
+
----------
|
13
|
+
|
14
|
+
Traditionally with Garb, you'll create a class for every report that you want. So a report that pulls back
|
15
|
+
visits might look like this:
|
16
|
+
|
17
|
+
class Visits
|
18
|
+
extend Garb::Model
|
19
|
+
|
20
|
+
metrics :visits
|
21
|
+
end
|
22
|
+
|
23
|
+
and one that gets visits and page views might look like this:
|
24
|
+
|
25
|
+
class VisitsAndPageViews
|
26
|
+
extend Garb::Model
|
27
|
+
|
28
|
+
metrics :visits, :pageviews
|
29
|
+
end
|
30
|
+
|
31
|
+
The you would use the report classes like this:
|
32
|
+
|
33
|
+
> Garb::Session.login(username, password) # this is only one option, please see Garb docs
|
34
|
+
> profile = Garb::Management::Profile.all.detect {|p| p.web_property_id == 'UA-XXXXXXX-X'}
|
35
|
+
> Visits.results(profile)
|
36
|
+
|
37
|
+
My idea was that, it would be nice to be able to avoid creating the report classes up-front by
|
38
|
+
utilising a common querying API (like a poor man's ActiveRecord API, if you will).
|
39
|
+
|
40
|
+
Usage
|
41
|
+
-----
|
42
|
+
|
43
|
+
So, when you have garb-reporter in your project, you no longer have to create those classes
|
44
|
+
(Visits or VisitsAndPageViews above) up-front.
|
45
|
+
|
46
|
+
The authentication and profile retrieval steps remain the same:
|
47
|
+
|
48
|
+
> Garb::Session.login(username, password) # this is only one option, please see Garb docs
|
49
|
+
> profile = Garb::Management::Profile.all.detect {|p| p.web_property_id == 'UA-XXXXXXX-X'}
|
50
|
+
|
51
|
+
But thereafter we just have to create a GarbReporter::Report instance with the profile:
|
52
|
+
|
53
|
+
> report = GarbReporter::Report.new(profile)
|
54
|
+
|
55
|
+
Then we can bust out some (albeit limit at this stage) querying awesomesauce:
|
56
|
+
|
57
|
+
> report.visits
|
58
|
+
> report.pageviews
|
59
|
+
> report.pageviews_and_visits
|
60
|
+
> report.pageviews_and_visits_by_date
|
61
|
+
> report.organicsearches
|
62
|
+
> report.organicsearches_by_source
|
63
|
+
|
64
|
+
You can probably see the pattern, but as long as you keep it legal with The Big G, a la:
|
65
|
+
|
66
|
+
http://code.google.com/apis/analytics/docs/gdata/dimsmets/dimsmets.html
|
67
|
+
|
68
|
+
...and format your methods like this:
|
69
|
+
|
70
|
+
> [metric]_and_[metric]_and_[metric]_by_[dimension]_and_[dimension]
|
71
|
+
|
72
|
+
you should be laughing.
|
73
|
+
|
74
|
+
|
75
|
+
TODOS
|
76
|
+
-----
|
77
|
+
|
78
|
+
* Implement respond_to on Report class to clean up validation
|
79
|
+
|
80
|
+
Run-time Requirements
|
81
|
+
---------------------
|
82
|
+
|
83
|
+
* Garb (tested against version 0.9.1)
|
84
|
+
|
85
|
+
Requirements for Testing
|
86
|
+
------------------------
|
87
|
+
|
88
|
+
* rspec
|
89
|
+
* i18n
|
90
|
+
* vcr
|
91
|
+
* fakeweb
|
92
|
+
|
93
|
+
Install
|
94
|
+
-------
|
95
|
+
|
96
|
+
gem install garb-reporter OR with bundler: gem 'garb-reporter' and `bundle install`
|
97
|
+
|
98
|
+
Contributors
|
99
|
+
------------
|
100
|
+
|
101
|
+
* Stu Liston (https://twitter.com/stuliston)
|
102
|
+
* Eric Harrison (https://twitter.com/gzminiz)
|
103
|
+
|
104
|
+
Thanks especially to the Garb core contributors. This tiny gem relies heavily on the great work they've produced
|
105
|
+
|
106
|
+
License
|
107
|
+
-------
|
108
|
+
|
109
|
+
(The MIT License)
|
110
|
+
|
111
|
+
Copyright (c) 2011 Stuart Liston
|
112
|
+
|
113
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
114
|
+
a copy of this software and associated documentation files (the
|
115
|
+
'Software'), to deal in the Software without restriction, including
|
116
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
117
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
118
|
+
permit persons to whom the Software is furnished to do so, subject to
|
119
|
+
the following conditions:
|
120
|
+
|
121
|
+
The above copyright notice and this permission notice shall be
|
122
|
+
included in all copies or substantial portions of the Software.
|
123
|
+
|
124
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
125
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
126
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
127
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
128
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
129
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
130
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/lib/garb-reporter.rb
CHANGED
@@ -10,13 +10,13 @@ module GarbReporter
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def method_missing(method, *args)
|
13
|
-
|
14
13
|
method_name = method.to_s
|
14
|
+
|
15
15
|
super unless valid_method_name?(method_name)
|
16
16
|
|
17
17
|
class_name = build_class_name(method_name)
|
18
18
|
klass = existing_report_class(class_name) || build_new_report_class(method_name, class_name)
|
19
|
-
klass.results(@profile)
|
19
|
+
klass.results(@profile, *args)
|
20
20
|
end
|
21
21
|
|
22
22
|
private
|
data/spec/garb_reporter_spec.rb
CHANGED
@@ -2,7 +2,7 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe GarbReporter do
|
4
4
|
|
5
|
-
before do
|
5
|
+
before(:all) do
|
6
6
|
|
7
7
|
# get VCR to serve us up a previously-canned http response for successful login
|
8
8
|
VCR.use_cassette('garb authentication') do
|
@@ -82,7 +82,49 @@ describe GarbReporter do
|
|
82
82
|
it 'should extract multiple dimensions' do
|
83
83
|
@report.send(:extract_dimensions, 'visits_by_date_and_office').should == [:date, :office]
|
84
84
|
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe 'build_new_report_class' do
|
88
|
+
|
89
|
+
before(:all) do
|
90
|
+
@klass = @report.send(:build_new_report_class, 'visits_by_date', 'VisitsByDate')
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'adds the class so the GarbReporter module' do
|
94
|
+
@klass.to_s.should == 'GarbReporter::VisitsByDate'
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'should give the new class the public "results" method from Garb::Model module' do
|
98
|
+
@klass.respond_to?(:results, false).should be_true
|
99
|
+
end
|
85
100
|
|
101
|
+
it 'should apply the correct metrics' do
|
102
|
+
report_params = @klass.instance_variable_get(:@metrics)
|
103
|
+
report_params.instance_variable_get(:@elements).should == [ :visits ]
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'should apply the correct dimensions' do
|
107
|
+
report_params = @klass.instance_variable_get(:@dimensions)
|
108
|
+
report_params.instance_variable_get(:@elements).should == [ :date ]
|
109
|
+
end
|
86
110
|
end
|
87
111
|
|
112
|
+
describe 'passing additional parameters to Garb' do
|
113
|
+
|
114
|
+
before(:all) do
|
115
|
+
@klass = GarbReporter.const_set('Exits', Class.new())
|
116
|
+
@stubbed_report = GarbReporter::Report.new(@profile)
|
117
|
+
@stubbed_report.stub!(:existing_report_class).and_return(@klass)
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'should pass no args when none are provided' do
|
121
|
+
@klass.should_receive(:results).once.with(@profile)
|
122
|
+
@stubbed_report.exits()
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'should pass start and end dates when provided' do
|
126
|
+
@klass.should_receive(:results).with(@profile, :start_date => '2011-01-01', :end_date => '2011-12-31')
|
127
|
+
@stubbed_report.exits(:start_date => '2011-01-01', :end_date => '2011-12-31')
|
128
|
+
end
|
129
|
+
end
|
88
130
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: garb-reporter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 4
|
10
|
+
version: 0.0.4
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Stu Liston
|
@@ -15,7 +15,8 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-12-02 00:00:00 +11:00
|
19
|
+
default_executable:
|
19
20
|
dependencies:
|
20
21
|
- !ruby/object:Gem::Dependency
|
21
22
|
name: garb
|
@@ -111,7 +112,7 @@ files:
|
|
111
112
|
- .rspec
|
112
113
|
- .rvmrc
|
113
114
|
- Gemfile
|
114
|
-
- README
|
115
|
+
- README.md
|
115
116
|
- Rakefile
|
116
117
|
- config/vcr_setup.rb
|
117
118
|
- garb-reporter.gemspec
|
@@ -119,8 +120,7 @@ files:
|
|
119
120
|
- lib/garb-reporter/version.rb
|
120
121
|
- spec/garb_reporter_spec.rb
|
121
122
|
- spec/spec_helper.rb
|
122
|
-
|
123
|
-
- vcr_cassettes/get_profile.yml
|
123
|
+
has_rdoc: true
|
124
124
|
homepage: https://github.com/stuliston/garb-reporter
|
125
125
|
licenses: []
|
126
126
|
|
@@ -150,7 +150,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
150
150
|
requirements: []
|
151
151
|
|
152
152
|
rubyforge_project: garb-reporter
|
153
|
-
rubygems_version: 1.
|
153
|
+
rubygems_version: 1.6.2
|
154
154
|
signing_key:
|
155
155
|
specification_version: 3
|
156
156
|
summary: Pimps out Garb by providing a report class with a standardised querying API
|
data/README
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
Welcome to garb-reporter!
|
@@ -1,38 +0,0 @@
|
|
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"
|
@@ -1,40 +0,0 @@
|
|
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"
|