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 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"