garb 0.9.0 → 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|