garb 0.5.1 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +65 -49
- data/Rakefile +1 -1
- data/lib/garb.rb +1 -1
- data/lib/garb/account.rb +15 -1
- data/lib/garb/data_request.rb +17 -4
- data/lib/garb/profile.rb +4 -3
- data/lib/garb/profile_reports.rb +15 -0
- data/lib/garb/reports.rb +5 -0
- data/lib/garb/reports/bounces.rb +5 -0
- data/lib/garb/reports/exits.rb +5 -0
- data/lib/garb/reports/pageviews.rb +5 -0
- data/lib/garb/reports/unique_pageviews.rb +5 -0
- data/lib/garb/reports/visits.rb +5 -0
- data/lib/garb/resource.rb +9 -0
- data/lib/garb/session.rb +11 -2
- data/lib/garb/version.rb +2 -2
- data/test/unit/garb/account_test.rb +7 -3
- data/test/unit/garb/data_request_test.rb +57 -7
- data/test/unit/garb/profile_reports_test.rb +29 -0
- data/test/unit/garb/session_test.rb +10 -1
- metadata +11 -5
- data/lib/garb/oauth_session.rb +0 -21
- data/lib/garb/profile_array.rb +0 -18
data/README.md
CHANGED
@@ -1,37 +1,12 @@
|
|
1
|
-
|
1
|
+
Garb
|
2
2
|
====
|
3
3
|
|
4
|
-
by Tony Pitale with much help from Justin Marney, Patrick Reagan and others at Viget Labs
|
5
|
-
|
6
4
|
http://github.com/vigetlabs/garb
|
7
5
|
|
8
6
|
Important Changes
|
9
7
|
=================
|
10
8
|
|
11
|
-
|
12
|
-
|
13
|
-
* Filters now have a new DSL so that I could toss Symbol operators (which conflict with DataMapper and MongoMapper)
|
14
|
-
* The method of passing a hash to filters no longer works, at all
|
15
|
-
|
16
|
-
Version 0.4.0
|
17
|
-
|
18
|
-
* Changes the api for filters and sort making it consistent with metrics/dimensions
|
19
|
-
* If you wish to clear the defaults defined on a class, you may use clear_(filters/sort/metrics/dimensions)
|
20
|
-
* To make a custom class using Garb::Resource, you must now extend instead of include the module
|
21
|
-
|
22
|
-
Version 0.3.2
|
23
|
-
|
24
|
-
* adds Profile.first which can be used to get the first profile with a table id, or web property id (UA number)
|
25
|
-
|
26
|
-
Version 0.2.4
|
27
|
-
|
28
|
-
* requires happymapper from rubygems, version 0.2.5. Be sure to update.
|
29
|
-
|
30
|
-
Version 0.2.0
|
31
|
-
|
32
|
-
* makes major changes (compared to 0.1.0) to the way garb is used to build reports.
|
33
|
-
* There is now both a module that gets included for generating defined classes,
|
34
|
-
* slight changes to the way that the Report class can be used.
|
9
|
+
Please read CHANGELOG
|
35
10
|
|
36
11
|
Description
|
37
12
|
-----------
|
@@ -43,13 +18,19 @@ Description
|
|
43
18
|
Basic Usage
|
44
19
|
===========
|
45
20
|
|
46
|
-
Login
|
47
|
-
|
21
|
+
Single User Login
|
22
|
+
-----------------
|
48
23
|
|
49
24
|
> Garb::Session.login(username, password)
|
25
|
+
|
26
|
+
OAuth Access Token
|
27
|
+
------------------
|
28
|
+
|
29
|
+
> Garb::Session.access_token = access_token # assign from oauth gem
|
50
30
|
|
51
31
|
Accounts
|
52
32
|
--------
|
33
|
+
|
53
34
|
> Garb::Account.all
|
54
35
|
|
55
36
|
Profiles
|
@@ -62,8 +43,8 @@ Profiles
|
|
62
43
|
> Garb::Profile.all
|
63
44
|
> profile = Garb::Profile.all.first
|
64
45
|
|
65
|
-
Define a Report Class
|
66
|
-
|
46
|
+
Define a Report Class
|
47
|
+
---------------------
|
67
48
|
|
68
49
|
class Exits
|
69
50
|
extend Garb::Resource
|
@@ -75,8 +56,20 @@ Define a Report Class and Get Results
|
|
75
56
|
filters do
|
76
57
|
eql(:page_path, 'season')
|
77
58
|
end
|
59
|
+
|
60
|
+
# alternative:
|
61
|
+
# filters :page_path.eql => 10
|
78
62
|
end
|
79
63
|
|
64
|
+
Get the Results
|
65
|
+
---------------
|
66
|
+
|
67
|
+
> Exits.results(profile)
|
68
|
+
|
69
|
+
OR shorthand
|
70
|
+
|
71
|
+
> profile.exits
|
72
|
+
|
80
73
|
Other Parameters
|
81
74
|
----------------
|
82
75
|
|
@@ -118,6 +111,9 @@ Building a Report
|
|
118
111
|
contains(:page_path, 'season')
|
119
112
|
gt(:exits, 100)
|
120
113
|
end
|
114
|
+
|
115
|
+
# or with a hash
|
116
|
+
# filters :page_path.contains => 'season', :exits.gt => 100
|
121
117
|
end
|
122
118
|
|
123
119
|
reports will be an array of OpenStructs with methods for the metrics and dimensions returned.
|
@@ -135,6 +131,9 @@ Build a One-Off Report
|
|
135
131
|
gte(:exits, 10)
|
136
132
|
and
|
137
133
|
|
134
|
+
# or with a hash
|
135
|
+
# report.filters :page_path.contains => 'season', :exits.gt => 100
|
136
|
+
|
138
137
|
report.results
|
139
138
|
|
140
139
|
Filtering
|
@@ -152,21 +151,21 @@ Filtering
|
|
152
151
|
|
153
152
|
Operators on metrics:
|
154
153
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
154
|
+
eql => '==',
|
155
|
+
not_eql => '!=',
|
156
|
+
gt => '>',
|
157
|
+
gte => '>=',
|
158
|
+
lt => '<',
|
159
|
+
lte => '<='
|
161
160
|
|
162
161
|
Operators on dimensions:
|
163
162
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
163
|
+
matches => '==',
|
164
|
+
does_not_match => '!=',
|
165
|
+
contains => '=~',
|
166
|
+
does_not_contain => '!~',
|
167
|
+
substring => '=@',
|
168
|
+
not_substring => '!@'
|
170
169
|
|
171
170
|
Given the previous example one-off report, we can add a line for filter:
|
172
171
|
|
@@ -174,10 +173,14 @@ Filtering
|
|
174
173
|
eql(:page_path, '/extend/effectively-using-git-with-subversion/')
|
175
174
|
end
|
176
175
|
|
176
|
+
Or, if you're comfortable using symbol operators:
|
177
|
+
|
178
|
+
report.filters :page_path.eql => '/extend/effectively-using-git-with-subversion/'
|
179
|
+
|
177
180
|
SSL
|
178
181
|
---
|
179
182
|
|
180
|
-
Version 0.2.3 includes support for real ssl encryption for authentication. First do:
|
183
|
+
Version 0.2.3 includes support for real ssl encryption for SINGLE USER authentication. First do:
|
181
184
|
|
182
185
|
Garb::Session.login(username, password, :secure => true)
|
183
186
|
|
@@ -191,27 +194,40 @@ TODOS
|
|
191
194
|
-----
|
192
195
|
|
193
196
|
* Sessions are currently global, which isn't awesome
|
194
|
-
* Single user login is the only supported method currently.
|
195
|
-
Intend to add hooks for using OAuth
|
196
197
|
* Read opensearch header in results
|
197
198
|
|
198
199
|
Requirements
|
199
200
|
------------
|
200
201
|
|
201
|
-
happymapper >= 0.3.0 (should also install libxml)
|
202
|
-
active_support >= 2.3.0
|
202
|
+
* happymapper >= 0.3.0 (should also install libxml)
|
203
|
+
* active_support >= 2.3.0
|
204
|
+
|
205
|
+
Requirements for Testing
|
206
|
+
------------------------
|
207
|
+
|
208
|
+
* jferris-mocha
|
209
|
+
* tpitale-shoulda (works with minitest)
|
203
210
|
|
204
211
|
Install
|
205
212
|
-------
|
206
213
|
|
207
214
|
sudo gem install garb
|
208
215
|
|
216
|
+
Contributors
|
217
|
+
------------
|
218
|
+
|
219
|
+
Many Thanks, for all their help, goes to:
|
220
|
+
|
221
|
+
* Patrick Reagan
|
222
|
+
* Justin Marney
|
223
|
+
* Nick Plante
|
224
|
+
|
209
225
|
License
|
210
226
|
-------
|
211
227
|
|
212
228
|
(The MIT License)
|
213
229
|
|
214
|
-
Copyright (c)
|
230
|
+
Copyright (c) 2010 Viget Labs
|
215
231
|
|
216
232
|
Permission is hereby granted, free of charge, to any person obtaining
|
217
233
|
a copy of this software and associated documentation files (the
|
data/Rakefile
CHANGED
@@ -12,7 +12,7 @@ spec = Gem::Specification.new do |s|
|
|
12
12
|
s.has_rdoc = false
|
13
13
|
s.rubyforge_project = 'viget'
|
14
14
|
s.summary = "Google Analytics API Ruby Wrapper"
|
15
|
-
s.authors = ['Tony Pitale'
|
15
|
+
s.authors = ['Tony Pitale']
|
16
16
|
s.email = 'tony.pitale@viget.com'
|
17
17
|
s.homepage = 'http://github.com/vigetlabs/garb'
|
18
18
|
s.files = %w(README.md Rakefile) + Dir.glob("lib/**/*")
|
data/lib/garb.rb
CHANGED
@@ -9,10 +9,10 @@ require 'happymapper'
|
|
9
9
|
require 'active_support'
|
10
10
|
|
11
11
|
require 'garb/version'
|
12
|
-
require 'garb/profile_array'
|
13
12
|
require 'garb/authentication_request'
|
14
13
|
require 'garb/data_request'
|
15
14
|
require 'garb/session'
|
15
|
+
require 'garb/profile_reports'
|
16
16
|
require 'garb/profile'
|
17
17
|
require 'garb/account'
|
18
18
|
require 'garb/filter_parameters'
|
data/lib/garb/account.rb
CHANGED
@@ -9,7 +9,21 @@ module Garb
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def self.all
|
12
|
-
Profile.all.group_to_array{|p| p.account_id}.map{|profiles| new(profiles)}
|
12
|
+
# Profile.all.group_to_array{|p| p.account_id}.map{|profiles| new(profiles)}
|
13
|
+
|
14
|
+
profile_groups = Profile.all.inject({}) do |hash, profile|
|
15
|
+
key = profile.account_id
|
16
|
+
|
17
|
+
if hash.has_key?(key)
|
18
|
+
hash[key] << profile
|
19
|
+
else
|
20
|
+
hash[key] = [profile]
|
21
|
+
end
|
22
|
+
|
23
|
+
hash
|
24
|
+
end
|
25
|
+
|
26
|
+
profile_groups.map {|k,v| v}.map {|profiles| new(profiles)}
|
13
27
|
end
|
14
28
|
end
|
15
29
|
end
|
data/lib/garb/data_request.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
module Garb
|
2
2
|
class DataRequest
|
3
|
+
class ClientError < StandardError; end
|
3
4
|
|
4
5
|
def initialize(base_url, parameters={})
|
5
6
|
@base_url = base_url
|
@@ -16,13 +17,25 @@ module Garb
|
|
16
17
|
end
|
17
18
|
|
18
19
|
def send_request
|
20
|
+
response = if Session.single_user?
|
21
|
+
single_user_request
|
22
|
+
elsif Session.oauth_user?
|
23
|
+
oauth_user_request
|
24
|
+
end
|
25
|
+
|
26
|
+
raise ClientError, response.body.inspect unless response.kind_of?(Net::HTTPSuccess)
|
27
|
+
response
|
28
|
+
end
|
29
|
+
|
30
|
+
def single_user_request
|
19
31
|
http = Net::HTTP.new(uri.host, uri.port)
|
20
32
|
http.use_ssl = true
|
21
33
|
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
22
|
-
|
23
|
-
raise response.body.inspect unless response.is_a?(Net::HTTPOK)
|
24
|
-
response
|
34
|
+
http.get("#{uri.path}#{query_string}", 'Authorization' => "GoogleLogin auth=#{Session.auth_token}")
|
25
35
|
end
|
26
36
|
|
37
|
+
def oauth_user_request
|
38
|
+
Session.access_token.get("#{uri}#{query_string}")
|
39
|
+
end
|
27
40
|
end
|
28
|
-
end
|
41
|
+
end
|
data/lib/garb/profile.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
module Garb
|
2
2
|
class Profile
|
3
|
-
|
3
|
+
|
4
|
+
include ProfileReports
|
5
|
+
|
4
6
|
attr_reader :table_id, :title, :account_name, :account_id, :web_property_id
|
5
7
|
|
6
8
|
class Property
|
@@ -44,8 +46,7 @@ module Garb
|
|
44
46
|
def self.all
|
45
47
|
url = "https://www.google.com/analytics/feeds/accounts/default"
|
46
48
|
response = DataRequest.new(url).send_request
|
47
|
-
|
48
|
-
ProfileArray.new(profiles)
|
49
|
+
Entry.parse(response.body).map {|entry| new(entry)}
|
49
50
|
end
|
50
51
|
|
51
52
|
def self.first(id)
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Garb
|
2
|
+
module ProfileReports
|
3
|
+
def self.add_report_method(klass)
|
4
|
+
# demodulize leaves potential to redefine
|
5
|
+
# these methods given different namespaces
|
6
|
+
method_name = klass.to_s.demodulize.underscore
|
7
|
+
|
8
|
+
class_eval <<-CODE
|
9
|
+
def #{method_name}(opts = {}, &block)
|
10
|
+
#{klass}.results(self, opts, &block)
|
11
|
+
end
|
12
|
+
CODE
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/garb/reports.rb
ADDED
data/lib/garb/resource.rb
CHANGED
@@ -3,6 +3,15 @@ module Garb
|
|
3
3
|
MONTH = 2592000
|
4
4
|
URL = "https://www.google.com/analytics/feeds/data"
|
5
5
|
|
6
|
+
def self.extended(base)
|
7
|
+
# define a method on a module that gets included into profile
|
8
|
+
# Exits would make:
|
9
|
+
# to enable profile.exits(options_hash, &block)
|
10
|
+
# returns Exits.results(self, options_hash, &block)
|
11
|
+
# every class defined which extends Resource will add to the module
|
12
|
+
ProfileReports.add_report_method(base)
|
13
|
+
end
|
14
|
+
|
6
15
|
%w(metrics dimensions sort).each do |parameter|
|
7
16
|
class_eval <<-CODE
|
8
17
|
def #{parameter}(*fields)
|
data/lib/garb/session.rb
CHANGED
@@ -2,12 +2,21 @@ module Garb
|
|
2
2
|
module Session
|
3
3
|
extend self
|
4
4
|
|
5
|
-
attr_accessor :auth_token, :email
|
6
|
-
|
5
|
+
attr_accessor :auth_token, :access_token, :email
|
6
|
+
|
7
|
+
# use only for single user authentication
|
7
8
|
def login(email, password, opts={})
|
8
9
|
self.email = email
|
9
10
|
auth_request = AuthenticationRequest.new(email, password, opts)
|
10
11
|
self.auth_token = auth_request.auth_token(opts)
|
11
12
|
end
|
13
|
+
|
14
|
+
def single_user?
|
15
|
+
auth_token && auth_token.is_a?(String)
|
16
|
+
end
|
17
|
+
|
18
|
+
def oauth_user?
|
19
|
+
!access_token.nil?
|
20
|
+
end
|
12
21
|
end
|
13
22
|
end
|
data/lib/garb/version.rb
CHANGED
@@ -6,10 +6,14 @@ module Garb
|
|
6
6
|
should "have an array of accounts with all profiles" do
|
7
7
|
p1 = stub(:account_id => '1111', :account_name => 'Blog 1')
|
8
8
|
p2 = stub(:account_id => '1112', :account_name => 'Blog 2')
|
9
|
-
|
10
|
-
|
11
|
-
Account.
|
9
|
+
|
10
|
+
Profile.stubs(:all).returns([p1,p2,p1,p2])
|
11
|
+
Account.stubs(:new).returns('account1', 'account2')
|
12
|
+
|
12
13
|
assert_equal ['account1','account2'], Account.all
|
14
|
+
assert_received(Profile, :all)
|
15
|
+
assert_received(Account, :new) {|e| e.with([p1,p1])}
|
16
|
+
assert_received(Account, :new) {|e| e.with([p2,p2])}
|
13
17
|
end
|
14
18
|
end
|
15
19
|
|
@@ -30,23 +30,73 @@ module Garb
|
|
30
30
|
assert_equal expected, DataRequest.new(url).uri
|
31
31
|
end
|
32
32
|
|
33
|
-
should "be able to
|
33
|
+
should "be able to send a request for a single user" do
|
34
|
+
Session.stubs(:single_user?).returns(true)
|
35
|
+
response = mock('Net::HTTPOK') do |m|
|
36
|
+
m.expects(:kind_of?).with(Net::HTTPSuccess).returns(true)
|
37
|
+
end
|
38
|
+
|
39
|
+
data_request = DataRequest.new('https://example.com/data', 'key' => 'value')
|
40
|
+
data_request.stubs(:single_user_request).returns(response)
|
41
|
+
data_request.send_request
|
42
|
+
|
43
|
+
assert_received(data_request, :single_user_request)
|
44
|
+
end
|
45
|
+
|
46
|
+
should "be able to send a request for an oauth user" do
|
47
|
+
Session.stubs(:single_user?).returns(false)
|
48
|
+
Session.stubs(:oauth_user?).returns(true)
|
49
|
+
response = mock('Net::HTTPOK') do |m|
|
50
|
+
m.expects(:kind_of?).with(Net::HTTPSuccess).returns(true)
|
51
|
+
end
|
52
|
+
|
53
|
+
data_request = DataRequest.new('https://example.com/data', 'key' => 'value')
|
54
|
+
data_request.stubs(:oauth_user_request).returns(response)
|
55
|
+
data_request.send_request
|
56
|
+
|
57
|
+
assert_received(data_request, :oauth_user_request)
|
58
|
+
end
|
59
|
+
|
60
|
+
should "raise if the request is unauthorized" do
|
61
|
+
Session.stubs(:single_user?).returns(false)
|
62
|
+
Session.stubs(:oauth_user?).returns(true)
|
63
|
+
response = mock('Net::HTTPUnauthorized', :body => 'Error')
|
64
|
+
|
65
|
+
data_request = DataRequest.new('https://example.com/data', 'key' => 'value')
|
66
|
+
data_request.stubs(:oauth_user_request).returns(response)
|
67
|
+
|
68
|
+
assert_raises(Garb::DataRequest::ClientError) do
|
69
|
+
data_request.send_request
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
should "be able to request via the ouath access token" do
|
74
|
+
access_token = stub(:get => "responseobject")
|
75
|
+
Session.stubs(:access_token).returns(access_token)
|
76
|
+
|
77
|
+
data_request = DataRequest.new('https://example.com/data', 'key' => 'value')
|
78
|
+
assert_equal 'responseobject', data_request.oauth_user_request
|
79
|
+
|
80
|
+
assert_received(Session, :access_token)
|
81
|
+
assert_received(access_token, :get) {|e| e.with('https://example.com/data?key=value')}
|
82
|
+
end
|
83
|
+
|
84
|
+
should "be able to request via http with an auth token" do
|
34
85
|
Session.expects(:auth_token).with().returns('toke')
|
35
86
|
response = mock
|
36
|
-
|
37
|
-
|
87
|
+
|
38
88
|
http = mock do |m|
|
39
89
|
m.expects(:use_ssl=).with(true)
|
40
90
|
m.expects(:verify_mode=).with(OpenSSL::SSL::VERIFY_NONE)
|
41
91
|
m.expects(:get).with('/data?key=value', 'Authorization' => 'GoogleLogin auth=toke').returns(response)
|
42
92
|
end
|
43
|
-
|
93
|
+
|
44
94
|
Net::HTTP.expects(:new).with('example.com', 443).returns(http)
|
45
|
-
|
95
|
+
|
46
96
|
data_request = DataRequest.new('https://example.com/data', 'key' => 'value')
|
47
|
-
assert_equal response, data_request.
|
97
|
+
assert_equal response, data_request.single_user_request
|
48
98
|
end
|
49
99
|
end
|
50
100
|
|
51
101
|
end
|
52
|
-
end
|
102
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', '..', '/test_helper')
|
2
|
+
|
3
|
+
module Garb
|
4
|
+
|
5
|
+
Exits = Class.new
|
6
|
+
|
7
|
+
class FakeProfile
|
8
|
+
include ProfileReports
|
9
|
+
end
|
10
|
+
|
11
|
+
class ProfileReportsTest < MiniTest::Unit::TestCase
|
12
|
+
context "The ProfileReports module" do
|
13
|
+
should "define a new method when given a class" do
|
14
|
+
ProfileReports.add_report_method(Exits)
|
15
|
+
assert_equal true, FakeProfile.new.respond_to?(:exits)
|
16
|
+
end
|
17
|
+
|
18
|
+
should "return results from the given class with options" do
|
19
|
+
results = [1,2,3]
|
20
|
+
Exits.stubs(:results).returns(results)
|
21
|
+
ProfileReports.add_report_method(Exits)
|
22
|
+
|
23
|
+
profile = FakeProfile.new
|
24
|
+
assert_equal results, profile.exits(:start => "now")
|
25
|
+
assert_received(Exits, :results) {|e| e.with(profile, :start => "now")}
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -28,7 +28,16 @@ module Garb
|
|
28
28
|
Session.login('email', 'password')
|
29
29
|
assert_equal 'email', Session.email
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
|
+
should "know if the Session is for a single user" do
|
33
|
+
Session.auth_token = "abcdefg1234567"
|
34
|
+
assert_equal true, Session.single_user?
|
35
|
+
end
|
36
|
+
|
37
|
+
should "know if the Session is for oauth" do
|
38
|
+
Session.access_token = 'some_oauth_access_token'
|
39
|
+
assert_equal true, Session.oauth_user?
|
40
|
+
end
|
32
41
|
end
|
33
42
|
|
34
43
|
end
|
metadata
CHANGED
@@ -1,16 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: garb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tony Pitale
|
8
|
-
- Patrick Reagan
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
11
|
|
13
|
-
date: 2010-
|
12
|
+
date: 2010-02-10 00:00:00 -05:00
|
14
13
|
default_executable:
|
15
14
|
dependencies:
|
16
15
|
- !ruby/object:Gem::Dependency
|
@@ -48,12 +47,17 @@ files:
|
|
48
47
|
- lib/garb/authentication_request.rb
|
49
48
|
- lib/garb/data_request.rb
|
50
49
|
- lib/garb/filter_parameters.rb
|
51
|
-
- lib/garb/oauth_session.rb
|
52
50
|
- lib/garb/profile.rb
|
53
|
-
- lib/garb/
|
51
|
+
- lib/garb/profile_reports.rb
|
54
52
|
- lib/garb/report.rb
|
55
53
|
- lib/garb/report_parameter.rb
|
56
54
|
- lib/garb/report_response.rb
|
55
|
+
- lib/garb/reports/bounces.rb
|
56
|
+
- lib/garb/reports/exits.rb
|
57
|
+
- lib/garb/reports/pageviews.rb
|
58
|
+
- lib/garb/reports/unique_pageviews.rb
|
59
|
+
- lib/garb/reports/visits.rb
|
60
|
+
- lib/garb/reports.rb
|
57
61
|
- lib/garb/resource.rb
|
58
62
|
- lib/garb/session.rb
|
59
63
|
- lib/garb/version.rb
|
@@ -68,6 +72,7 @@ files:
|
|
68
72
|
- test/unit/garb/data_request_test.rb
|
69
73
|
- test/unit/garb/filter_parameters_test.rb
|
70
74
|
- test/unit/garb/oauth_session_test.rb
|
75
|
+
- test/unit/garb/profile_reports_test.rb
|
71
76
|
- test/unit/garb/profile_test.rb
|
72
77
|
- test/unit/garb/report_parameter_test.rb
|
73
78
|
- test/unit/garb/report_response_test.rb
|
@@ -114,6 +119,7 @@ test_files:
|
|
114
119
|
- test/unit/garb/data_request_test.rb
|
115
120
|
- test/unit/garb/filter_parameters_test.rb
|
116
121
|
- test/unit/garb/oauth_session_test.rb
|
122
|
+
- test/unit/garb/profile_reports_test.rb
|
117
123
|
- test/unit/garb/profile_test.rb
|
118
124
|
- test/unit/garb/report_parameter_test.rb
|
119
125
|
- test/unit/garb/report_response_test.rb
|
data/lib/garb/oauth_session.rb
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
module Garb
|
2
|
-
class OAuthSession
|
3
|
-
attr_accessor :access_token
|
4
|
-
|
5
|
-
OAuthGetRequestToken = "https://www.google.com/accounts/OAuthGetRequestToken"
|
6
|
-
OAuthAuthorizeToken = "https://www.google.com/accounts/OAuthAuthorizeToken"
|
7
|
-
OAuthGetAccessToken = "https://www.google.com/accounts/OAuthGetAccessToken"
|
8
|
-
|
9
|
-
def get_request_token
|
10
|
-
|
11
|
-
end
|
12
|
-
|
13
|
-
def authorization_request
|
14
|
-
|
15
|
-
end
|
16
|
-
|
17
|
-
def get_access_token
|
18
|
-
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
data/lib/garb/profile_array.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
module Garb
|
2
|
-
class ProfileArray < Array
|
3
|
-
def group_to_array
|
4
|
-
h = Hash.new
|
5
|
-
|
6
|
-
each do |element|
|
7
|
-
key = yield(element)
|
8
|
-
if h.has_key?(key)
|
9
|
-
h[key] << element
|
10
|
-
else
|
11
|
-
h[key] = [element]
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
h.map{|k,v| v}
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|