garb 0.9.0 → 0.9.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/README.md +5 -9
- data/lib/garb.rb +1 -0
- data/lib/garb/filter_parameters.rb +2 -1
- data/lib/garb/management/feed.rb +1 -1
- data/lib/garb/model.rb +6 -4
- data/lib/garb/report_response.rb +27 -3
- data/lib/garb/result_set.rb +21 -0
- data/lib/garb/version.rb +1 -1
- data/test/fixtures/report_feed.xml +2 -0
- data/test/unit/garb/coverage/index.html +1 -1
- data/test/unit/garb/coverage/resultset.yml +1 -1
- data/test/unit/garb/filter_parameters_test.rb +9 -0
- data/test/unit/garb/management/coverage/index.html +1 -1
- data/test/unit/garb/management/coverage/resultset.yml +1 -1
- data/test/unit/garb/management/feed_test.rb +5 -0
- data/test/unit/garb/model_test.rb +8 -3
- data/test/unit/garb/report_response_test.rb +15 -5
- metadata +4 -3
data/README.md
CHANGED
@@ -48,7 +48,7 @@ Accounts, WebProperties, Profiles, and Goals
|
|
48
48
|
Profiles for a UA- Number (a WebProperty)
|
49
49
|
--------
|
50
50
|
|
51
|
-
> profile =
|
51
|
+
> profile = Garb::Management::Profile.all.detect {|p| p.web_property_id == 'UA-XXXXXXX-X'}
|
52
52
|
|
53
53
|
Define a Report Class
|
54
54
|
---------------------
|
@@ -82,14 +82,13 @@ Other Parameters
|
|
82
82
|
Metrics & Dimensions
|
83
83
|
--------------------
|
84
84
|
|
85
|
-
**Metrics and Dimensions are very complex because of the ways in which
|
85
|
+
**Metrics and Dimensions are very complex because of the ways in which they can and cannot be combined.**
|
86
86
|
|
87
87
|
I suggest reading the google documentation to familiarize yourself with this.
|
88
88
|
|
89
89
|
http://code.google.com/apis/analytics/docs/gdata/gdataReferenceDimensionsMetrics.html#bounceRate
|
90
90
|
|
91
|
-
When you've returned, you can pass the appropriate combinations
|
92
|
-
to garb, as an array, of symbols. Or you can simply push a symbol into the array.
|
91
|
+
When you've returned, you can pass the appropriate combinations to Garb, as symbols.
|
93
92
|
|
94
93
|
Filtering
|
95
94
|
---------
|
@@ -98,11 +97,8 @@ Filtering
|
|
98
97
|
|
99
98
|
http://code.google.com/apis/analytics/docs/gdata/gdataReference.html#filtering
|
100
99
|
|
101
|
-
We handle filtering as an array of hashes that you can push into,
|
102
|
-
which will be joined together (AND'd)
|
103
|
-
|
104
100
|
Here is what we can do currently:
|
105
|
-
(the operator is a method on a symbol metric or dimension)
|
101
|
+
(the operator is a method on a symbol for the appropriate metric or dimension)
|
106
102
|
|
107
103
|
Operators on metrics:
|
108
104
|
|
@@ -122,7 +118,7 @@ Filtering
|
|
122
118
|
substring => '=@',
|
123
119
|
not_substring => '!@'
|
124
120
|
|
125
|
-
Given the previous Exits example report, we can add an
|
121
|
+
Given the previous Exits example report in shorthand, we can add an option for filter:
|
126
122
|
|
127
123
|
profile.exits(:filters => {:page_path.eql => '/extend/effectively-using-git-with-subversion/')
|
128
124
|
|
data/lib/garb.rb
CHANGED
@@ -31,7 +31,8 @@ module Garb
|
|
31
31
|
value = self.parameters.map do |param|
|
32
32
|
param.map do |k,v|
|
33
33
|
next unless k.is_a?(SymbolOperator)
|
34
|
-
|
34
|
+
escaped_v = v.to_s.gsub(/([,;\\])/) {|c| '\\'+c}
|
35
|
+
"#{URI.encode(k.to_google_analytics, /[=<>]/)}#{CGI::escape(escaped_v)}"
|
35
36
|
end.join('%3B') # Hash AND (no duplicate keys), escape char for ';' fixes oauth
|
36
37
|
end.join(',') # Array OR
|
37
38
|
|
data/lib/garb/management/feed.rb
CHANGED
data/lib/garb/model.rb
CHANGED
@@ -26,7 +26,9 @@ module Garb
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def results(profile, options = {})
|
29
|
-
|
29
|
+
start_date = options.fetch(:start_date, Time.now - MONTH)
|
30
|
+
end_date = options.fetch(:end_date, Time.now)
|
31
|
+
default_params = build_default_params(profile, start_date, end_date)
|
30
32
|
|
31
33
|
param_set = [
|
32
34
|
default_params,
|
@@ -70,11 +72,11 @@ module Garb
|
|
70
72
|
sort
|
71
73
|
end
|
72
74
|
|
73
|
-
def build_default_params(profile)
|
75
|
+
def build_default_params(profile, start_date, end_date)
|
74
76
|
{
|
75
77
|
'ids' => Garb.to_ga(profile.id),
|
76
|
-
'start-date' => format_time(
|
77
|
-
'end-date' => format_time(
|
78
|
+
'start-date' => format_time(start_date),
|
79
|
+
'end-date' => format_time(end_date)
|
78
80
|
}
|
79
81
|
end
|
80
82
|
|
data/lib/garb/report_response.rb
CHANGED
@@ -8,7 +8,16 @@ module Garb
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def results
|
11
|
-
@results
|
11
|
+
if @results.nil?
|
12
|
+
@results = ResultSet.new(parse)
|
13
|
+
@results.total_results = parse_total_results
|
14
|
+
@results.sampled = parse_sampled_flag
|
15
|
+
end
|
16
|
+
|
17
|
+
@results
|
18
|
+
end
|
19
|
+
|
20
|
+
def sampled?
|
12
21
|
end
|
13
22
|
|
14
23
|
private
|
@@ -21,8 +30,23 @@ module Garb
|
|
21
30
|
end
|
22
31
|
|
23
32
|
def entries
|
24
|
-
|
25
|
-
|
33
|
+
feed? ? [parsed_xml['feed']['entry']].flatten.compact : []
|
34
|
+
end
|
35
|
+
|
36
|
+
def parse_total_results
|
37
|
+
feed? ? parsed_xml['feed']['openSearch:totalResults'].to_i : 0
|
38
|
+
end
|
39
|
+
|
40
|
+
def parse_sampled_flag
|
41
|
+
feed? ? (parsed_xml['feed']['dxp:containsSampledData'] == 'true') : false
|
42
|
+
end
|
43
|
+
|
44
|
+
def parsed_xml
|
45
|
+
@parsed_xml ||= Crack::XML.parse(@xml)
|
46
|
+
end
|
47
|
+
|
48
|
+
def feed?
|
49
|
+
!parsed_xml['feed'].nil?
|
26
50
|
end
|
27
51
|
|
28
52
|
def values_for(entry)
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Garb
|
2
|
+
class ResultSet
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
attr_accessor :total_results, :sampled
|
6
|
+
|
7
|
+
alias :sampled? :sampled
|
8
|
+
|
9
|
+
def initialize(results)
|
10
|
+
@results = results
|
11
|
+
end
|
12
|
+
|
13
|
+
def each(&block)
|
14
|
+
@results.each(&block)
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_a
|
18
|
+
@results
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/garb/version.rb
CHANGED
@@ -14,6 +14,8 @@
|
|
14
14
|
</author>
|
15
15
|
<openSearch:startIndex>3</openSearch:startIndex>
|
16
16
|
<openSearch:itemsPerPage>4</openSearch:itemsPerPage>
|
17
|
+
<openSearch:totalResults>18</openSearch:totalResults>
|
18
|
+
<dxp:containsSampledData>true</dxp:containsSampledData>
|
17
19
|
<ga:webPropertyID>UA-983247-67</ga:webPropertyID>
|
18
20
|
<ga:start-date>2008-01-01</ga:start-date>
|
19
21
|
<ga:end-date>2008-01-02</ga:end-date>
|
@@ -21,7 +21,7 @@
|
|
21
21
|
<img src="./assets/0.3.9/loading.gif" alt="loading"/>
|
22
22
|
</div>
|
23
23
|
<div id="wrapper" style="display:none;">
|
24
|
-
<div class="timestamp">Generated <abbr class="timeago" title="
|
24
|
+
<div class="timestamp">Generated <abbr class="timeago" title="2011-01-08T20:21:01-05:00">2011-01-08T20:21:01-05:00</abbr></div>
|
25
25
|
<ul class="group_tabs"></ul>
|
26
26
|
|
27
27
|
<div id="content">
|
@@ -53,6 +53,15 @@ module Garb
|
|
53
53
|
params = {'filters' => 'ga:pagePath%3D~New+York'}
|
54
54
|
assert_equal params, @filter_parameters.to_params
|
55
55
|
end
|
56
|
+
|
57
|
+
should "escape comma, semicolon, and backslash in values" do
|
58
|
+
@filter_parameters.filters do
|
59
|
+
eql(:url, 'this;that,thing\other')
|
60
|
+
end
|
61
|
+
|
62
|
+
params = {'filters' => 'ga:url%3D%3Dthis%5C%3Bthat%5C%2Cthing%5C%5Cother'}
|
63
|
+
assert_equal params, @filter_parameters.to_params
|
64
|
+
end
|
56
65
|
end
|
57
66
|
end
|
58
67
|
end
|
@@ -21,7 +21,7 @@
|
|
21
21
|
<img src="./assets/0.3.9/loading.gif" alt="loading"/>
|
22
22
|
</div>
|
23
23
|
<div id="wrapper" style="display:none;">
|
24
|
-
<div class="timestamp">Generated <abbr class="timeago" title="
|
24
|
+
<div class="timestamp">Generated <abbr class="timeago" title="2011-01-08T19:38:09-05:00">2011-01-08T19:38:09-05:00</abbr></div>
|
25
25
|
<ul class="group_tabs"></ul>
|
26
26
|
|
27
27
|
<div id="content">
|
@@ -23,6 +23,11 @@ module Garb
|
|
23
23
|
assert_equal ['entry1', 'entry2'], @feed.entries
|
24
24
|
end
|
25
25
|
|
26
|
+
should "handle case of a single entry" do
|
27
|
+
@feed.stubs(:parsed_response).returns({'feed' => {'entry' => {'profile_id' => '12345'}}})
|
28
|
+
assert_equal [{'profile_id' => '12345'}], @feed.entries
|
29
|
+
end
|
30
|
+
|
26
31
|
should "have an empty array for entries without a response" do
|
27
32
|
@feed.stubs(:parsed_response).returns(nil)
|
28
33
|
assert_equal [], @feed.entries
|
@@ -64,7 +64,7 @@ module Garb
|
|
64
64
|
@test_model.stubs(:dimensions).returns(stub(:to_params => {'dimensions' => 'ga:pagePath'}))
|
65
65
|
|
66
66
|
now = Time.now
|
67
|
-
Time.stubs(:
|
67
|
+
Time.stubs(:now).returns(now)
|
68
68
|
|
69
69
|
# p @profile.id
|
70
70
|
|
@@ -115,7 +115,13 @@ module Garb
|
|
115
115
|
assert_data_params(@params.merge({'start-index' => 10}))
|
116
116
|
end
|
117
117
|
|
118
|
-
|
118
|
+
should "be able to shift the date range" do
|
119
|
+
start_date = (Time.now - 1296000)
|
120
|
+
end_date = Time.now
|
121
|
+
|
122
|
+
assert_equal ['result'], @test_model.results(@profile, :start_date => start_date, :end_date => end_date)
|
123
|
+
assert_data_params(@params.merge({'start-date' => start_date.strftime('%Y-%m-%d'), 'end-date' => end_date.strftime('%Y-%m-%d')}))
|
124
|
+
end
|
119
125
|
|
120
126
|
should "return a set of results in the defined class" do
|
121
127
|
@test_model.stubs(:instance_klass).returns(ResultKlass)
|
@@ -125,7 +131,6 @@ module Garb
|
|
125
131
|
end
|
126
132
|
end
|
127
133
|
|
128
|
-
# should "have a block syntax for filtering results"
|
129
134
|
# should "return results as an array of the class it belongs to, if that class is an ActiveRecord descendant"
|
130
135
|
# should "return results as an array of the class it belongs to, if that class is a DataMapper descendant"
|
131
136
|
# should "return results as an array of the class it belongs to, if that class is a MongoMapper descendant"
|
@@ -7,30 +7,40 @@ module Garb
|
|
7
7
|
context "A ReportResponse" do
|
8
8
|
context "with a report feed" do
|
9
9
|
setup do
|
10
|
-
@
|
10
|
+
@xml = File.read(File.join(File.dirname(__FILE__), '..', '..', "/fixtures/report_feed.xml"))
|
11
11
|
end
|
12
12
|
|
13
13
|
should "parse results from atom xml" do
|
14
|
-
response = ReportResponse.new(@
|
14
|
+
response = ReportResponse.new(@xml)
|
15
15
|
assert_equal ['33', '2', '1'], response.results.map(&:pageviews)
|
16
16
|
end
|
17
17
|
|
18
18
|
should "default to returning an array of OpenStruct objects" do
|
19
|
-
response = ReportResponse.new(@
|
19
|
+
response = ReportResponse.new(@xml)
|
20
20
|
assert_equal [OpenStruct, OpenStruct, OpenStruct], response.results.map(&:class)
|
21
21
|
end
|
22
22
|
|
23
23
|
should "return an array of instances of a specified class" do
|
24
|
-
response = ReportResponse.new(@
|
24
|
+
response = ReportResponse.new(@xml, SpecialKlass)
|
25
25
|
assert_equal [SpecialKlass, SpecialKlass, SpecialKlass], response.results.map(&:class)
|
26
26
|
end
|
27
|
+
|
28
|
+
should "know the total number of results" do
|
29
|
+
response = ReportResponse.new(@xml)
|
30
|
+
assert_equal 18, response.results.total_results
|
31
|
+
end
|
32
|
+
|
33
|
+
should "know if the data has been sampled" do
|
34
|
+
response = ReportResponse.new(@xml)
|
35
|
+
assert_equal true, response.results.sampled?
|
36
|
+
end
|
27
37
|
end
|
28
38
|
|
29
39
|
should "return an empty array if there are no results" do
|
30
40
|
response = ReportResponse.new("result xml")
|
31
41
|
Crack::XML.stubs(:parse).with("result xml").returns({'feed' => {'entry' => nil}})
|
32
42
|
|
33
|
-
assert_equal [], response.results
|
43
|
+
assert_equal [], response.results.to_a
|
34
44
|
end
|
35
45
|
end
|
36
46
|
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 9
|
8
|
-
-
|
9
|
-
version: 0.9.
|
8
|
+
- 1
|
9
|
+
version: 0.9.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Tony Pitale
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date:
|
17
|
+
date: 2011-01-08 00:00:00 -05:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -84,6 +84,7 @@ files:
|
|
84
84
|
- lib/garb/reports/visits.rb
|
85
85
|
- lib/garb/reports.rb
|
86
86
|
- lib/garb/resource.rb
|
87
|
+
- lib/garb/result_set.rb
|
87
88
|
- lib/garb/session.rb
|
88
89
|
- lib/garb/step.rb
|
89
90
|
- lib/garb/version.rb
|