garb-reporter 0.0.3 → 0.0.4

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 CHANGED
@@ -4,3 +4,4 @@ Gemfile.lock
4
4
  pkg/*
5
5
  .DS_Store
6
6
  notes
7
+ vcr_cassettes
@@ -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.
@@ -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
@@ -1,3 +1,3 @@
1
1
  module GarbReporter
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -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
@@ -1,6 +1,6 @@
1
1
  require "config/vcr_setup"
2
2
  require "garb"
3
- require "report"
3
+ require "garb-reporter"
4
4
 
5
5
  RSpec.configure do |config|
6
6
  # some (optional) config here
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: 25
4
+ hash: 23
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 3
10
- version: 0.0.3
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-11-30 00:00:00 Z
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
- - vcr_cassettes/garb_authentication.yml
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.8.10
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/&quot;C0cHSXw7fSp7I2A9WhRREUw.&quot;" 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"