garb-no-activesupport 0.7.3 → 0.7.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/README.md +1 -1
- data/Rakefile +1 -1
- data/lib/garb.rb +8 -4
- data/lib/garb/profile.rb +12 -32
- data/lib/garb/report_response.rb +16 -45
- data/lib/garb/version.rb +1 -1
- data/lib/string_ext.rb +4 -0
- data/test/fixtures/profile_feed.xml +30 -32
- data/test/fixtures/report_feed.xml +4 -4
- data/test/unit/garb/profile_test.rb +23 -35
- data/test/unit/garb/report_response_test.rb +5 -20
- metadata +7 -7
data/README.md
CHANGED
data/Rakefile
CHANGED
@@ -18,7 +18,7 @@ spec = Gem::Specification.new do |s|
|
|
18
18
|
s.files = %w(README.md Rakefile) + Dir.glob("lib/**/*")
|
19
19
|
s.test_files = Dir.glob("test/**/*")
|
20
20
|
|
21
|
-
s.add_dependency("
|
21
|
+
s.add_dependency("crack", [">= 0.1.6"])
|
22
22
|
end
|
23
23
|
|
24
24
|
Rake::GemPackageTask.new(spec) do |pkg|
|
data/lib/garb.rb
CHANGED
@@ -5,7 +5,7 @@ require 'net/https'
|
|
5
5
|
|
6
6
|
require 'cgi'
|
7
7
|
require 'ostruct'
|
8
|
-
require '
|
8
|
+
require 'crack'
|
9
9
|
|
10
10
|
require 'string_ext'
|
11
11
|
require 'garb/version'
|
@@ -25,14 +25,18 @@ require 'support'
|
|
25
25
|
|
26
26
|
module Garb
|
27
27
|
GA = "http://schemas.google.com/analytics/2008"
|
28
|
-
|
29
|
-
|
28
|
+
|
29
|
+
extend self
|
30
|
+
|
31
|
+
def to_google_analytics(thing)
|
30
32
|
return thing.to_google_analytics if thing.respond_to?(:to_google_analytics)
|
31
33
|
|
32
34
|
"ga:#{thing.to_s.camelize(:lower)}"
|
33
35
|
end
|
36
|
+
alias :to_ga :to_google_analytics
|
34
37
|
|
35
|
-
def
|
38
|
+
def from_google_analytics(thing)
|
36
39
|
thing.to_s.gsub(/^ga\:/, '').underscore
|
37
40
|
end
|
41
|
+
alias :from_ga :from_google_analytics
|
38
42
|
end
|
data/lib/garb/profile.rb
CHANGED
@@ -4,54 +4,34 @@ module Garb
|
|
4
4
|
include ProfileReports
|
5
5
|
|
6
6
|
attr_reader :session, :table_id, :title, :account_name, :account_id, :web_property_id
|
7
|
-
|
8
|
-
class Property
|
9
|
-
include HappyMapper
|
10
|
-
|
11
|
-
tag 'property'
|
12
|
-
namespace 'http://schemas.google.com/analytics/2009'
|
13
|
-
|
14
|
-
attribute :name, String
|
15
|
-
attribute :value, String
|
16
|
-
|
17
|
-
def instance_name
|
18
|
-
Garb.from_google_analytics(name)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
class Entry
|
23
|
-
include HappyMapper
|
24
|
-
|
25
|
-
tag 'entry'
|
26
|
-
|
27
|
-
element :title, String
|
28
|
-
element :tableId, String, :namespace => 'http://schemas.google.com/analytics/2009'
|
29
|
-
|
30
|
-
has_many :properties, Property
|
31
|
-
end
|
32
7
|
|
33
8
|
def initialize(entry, session)
|
34
9
|
@session = session
|
35
|
-
@title = entry
|
36
|
-
@table_id = entry
|
10
|
+
@title = entry['title']
|
11
|
+
@table_id = entry['dxp:tableId']
|
37
12
|
|
38
|
-
entry.
|
39
|
-
instance_variable_set :"@#{p
|
13
|
+
entry['dxp:property'].each do |p|
|
14
|
+
instance_variable_set :"@#{Garb.from_ga(p['name'])}", p['value']
|
40
15
|
end
|
41
16
|
end
|
42
17
|
|
43
18
|
def id
|
44
|
-
Garb.
|
19
|
+
Garb.from_ga(@table_id)
|
45
20
|
end
|
46
21
|
|
47
22
|
def self.all(session = Session)
|
48
23
|
url = "https://www.google.com/analytics/feeds/accounts/default"
|
49
|
-
response = DataRequest.new(session, url).send_request
|
50
|
-
|
24
|
+
response = DataRequest.new(session, url).send_request
|
25
|
+
parse(response.body).map {|entry| new(entry, session)}
|
51
26
|
end
|
52
27
|
|
53
28
|
def self.first(id, session = Session)
|
54
29
|
all(session).detect {|profile| profile.id == id || profile.web_property_id == id }
|
55
30
|
end
|
31
|
+
|
32
|
+
def self.parse(response_body)
|
33
|
+
entry_hash = Crack::XML.parse(response_body)
|
34
|
+
entry_hash ? [entry_hash['feed']['entry']].flatten : []
|
35
|
+
end
|
56
36
|
end
|
57
37
|
end
|
data/lib/garb/report_response.rb
CHANGED
@@ -1,62 +1,33 @@
|
|
1
1
|
module Garb
|
2
2
|
class ReportResponse
|
3
|
-
|
3
|
+
KEYS = ['dxp:metric', 'dxp:dimension']
|
4
4
|
|
5
5
|
def initialize(response_body)
|
6
6
|
@xml = response_body
|
7
7
|
end
|
8
|
-
|
9
|
-
def parse
|
10
|
-
entries = Entry.parse(@xml)
|
11
|
-
|
12
|
-
@results = entries.collect do |entry|
|
13
|
-
hash = {}
|
14
|
-
|
15
|
-
entry.metrics.each do |m|
|
16
|
-
name = m.name.sub(/^ga\:/,'').underscore
|
17
|
-
hash.merge!({name => m.value})
|
18
|
-
end
|
19
|
-
|
20
|
-
entry.dimensions.each do |d|
|
21
|
-
name = d.name.sub(/^ga\:/,'').underscore
|
22
|
-
hash.merge!({name => d.value})
|
23
|
-
end
|
24
|
-
|
25
|
-
OpenStruct.new(hash)
|
26
|
-
end
|
27
|
-
end
|
28
8
|
|
29
9
|
def results
|
30
|
-
@results
|
10
|
+
@results ||= parse
|
31
11
|
end
|
32
|
-
|
33
|
-
class Metric
|
34
|
-
include HappyMapper
|
35
12
|
|
36
|
-
|
37
|
-
|
13
|
+
private
|
14
|
+
def parse
|
15
|
+
entries.map do |entry|
|
16
|
+
hash = values_for(entry).inject({}) do |h, v|
|
17
|
+
h.merge(Garb.from_ga(v['name']) => v['value'])
|
18
|
+
end
|
38
19
|
|
39
|
-
|
40
|
-
|
20
|
+
OpenStruct.new(hash)
|
21
|
+
end
|
41
22
|
end
|
42
|
-
|
43
|
-
class Dimension
|
44
|
-
include HappyMapper
|
45
|
-
|
46
|
-
tag 'dimension'
|
47
|
-
namespace 'http://schemas.google.com/analytics/2009'
|
48
23
|
|
49
|
-
|
50
|
-
|
24
|
+
def entries
|
25
|
+
entry_hash = Crack::XML.parse(@xml)
|
26
|
+
entry_hash ? [entry_hash['feed']['entry']].flatten : []
|
51
27
|
end
|
52
|
-
|
53
|
-
class Entry
|
54
|
-
include HappyMapper
|
55
|
-
|
56
|
-
tag 'entry'
|
57
28
|
|
58
|
-
|
59
|
-
|
29
|
+
def values_for(entry)
|
30
|
+
KEYS.map {|k| entry[k]}.flatten.compact
|
60
31
|
end
|
61
32
|
end
|
62
|
-
end
|
33
|
+
end
|
data/lib/garb/version.rb
CHANGED
data/lib/string_ext.rb
CHANGED
@@ -1,40 +1,38 @@
|
|
1
|
-
<?xml version=
|
2
|
-
<feed xmlns=
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
<openSearch:itemsPerPage>2</openSearch:itemsPerPage>
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:dxp="http://schemas.google.com/analytics/2009" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/">
|
3
|
+
<id>http://www.google.com/analytics/feeds/accounts/tpitale@gmail.com</id>
|
4
|
+
<updated>2009-10-02T07:47:35.000-07:00</updated>
|
5
|
+
<title type="text">Profile list for tpitale@gmail.com</title>
|
6
|
+
<link rel="self" type="application/atom+xml" href="http://www.google.com/analytics/feeds/accounts/default"/>
|
7
|
+
<author><name>Google Analytics</name></author>
|
8
|
+
<generator version="1.0">Google Analytics</generator>
|
9
|
+
<openSearch:totalResults>2</openSearch:totalResults>
|
10
|
+
<openSearch:startIndex>1</openSearch:startIndex>
|
11
|
+
<openSearch:itemsPerPage>2</openSearch:itemsPerPage>
|
13
12
|
<entry>
|
14
13
|
<id>http://www.google.com/analytics/feeds/accounts/ga:12345</id>
|
15
14
|
<updated>2008-07-21T14:05:57.000-07:00</updated>
|
16
|
-
<title type=
|
17
|
-
|
18
|
-
<dxp:property name=
|
19
|
-
<dxp:property name=
|
20
|
-
<dxp:property name=
|
21
|
-
<dxp:property name=
|
22
|
-
|
23
|
-
|
24
|
-
|
15
|
+
<title type="text">Historical</title>
|
16
|
+
<link rel="alternate" type="text/html" href="http://www.google.com/analytics"/>
|
17
|
+
<dxp:property name="ga:accountId" value="1111"/>
|
18
|
+
<dxp:property name="ga:accountName" value="Blog Beta"/>
|
19
|
+
<dxp:property name="ga:profileId" value="1212"/>
|
20
|
+
<dxp:property name="ga:webPropertyId" value="UA-1111-1"/>
|
21
|
+
<dxp:property name="ga:currency" value="USD"/>
|
22
|
+
<dxp:property name="ga:timezone" value="America/New_York"/>
|
23
|
+
<dxp:tableId>ga:12345</dxp:tableId>
|
25
24
|
</entry>
|
26
25
|
<entry>
|
27
26
|
<id>http://www.google.com/analytics/feeds/accounts/ga:12346</id>
|
28
27
|
<updated>2008-11-24T11:51:07.000-08:00</updated>
|
29
|
-
<title type=
|
30
|
-
|
31
|
-
<dxp:property name=
|
32
|
-
<dxp:property name=
|
33
|
-
<dxp:property name=
|
34
|
-
<dxp:property name=
|
35
|
-
|
36
|
-
|
37
|
-
|
28
|
+
<title type="text">Presently</title>
|
29
|
+
<link rel="alternate" type="text/html" href="http://www.google.com/analytics"/>
|
30
|
+
<dxp:property name="ga:accountId" value="1111"/>
|
31
|
+
<dxp:property name="ga:accountName" value="Blog Beta"/>
|
32
|
+
<dxp:property name="ga:profileId" value="1213"/>
|
33
|
+
<dxp:property name="ga:webPropertyId" value="UA-1111-2"/>
|
34
|
+
<dxp:property name="ga:currency" value="USD"/>
|
35
|
+
<dxp:property name="ga:timezone" value="America/New_York"/>
|
36
|
+
<dxp:tableId>ga:12346</dxp:tableId>
|
38
37
|
</entry>
|
39
|
-
</feed>
|
40
|
-
|
38
|
+
</feed>
|
@@ -1,8 +1,8 @@
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
-
<feed xmlns=
|
3
|
-
xmlns:openSearch=
|
4
|
-
xmlns:dxp=
|
5
|
-
xmlns:ga=
|
2
|
+
<feed xmlns="http://www.w3.org/2005/Atom"
|
3
|
+
xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/"
|
4
|
+
xmlns:dxp="http://schemas.google.com/analytics/2009"
|
5
|
+
xmlns:ga="http://schemas.google.com/analytics/2008">
|
6
6
|
<id>http://www.google.com/analytics/feeds/data?ids=ga:983247&dimensions=ga:country,ga:city&metrics=ga:pageViews&start-date=2008-01-01&end-date=2008-01-02</id>
|
7
7
|
<updated>2008-01-02T15:59:59.999-08:00 </updated>
|
8
8
|
<title type="text">Google Analytics Data for Profile 983247</title>
|
@@ -5,29 +5,19 @@ module Garb
|
|
5
5
|
|
6
6
|
context "The Profile class" do
|
7
7
|
setup {@session = Session.new}
|
8
|
-
|
8
|
+
|
9
9
|
should "be able to return a list of all profiles" do
|
10
10
|
url = 'https://www.google.com/analytics/feeds/accounts/default'
|
11
|
-
|
11
|
+
|
12
12
|
xml = read_fixture('profile_feed.xml')
|
13
|
-
|
14
|
-
data_request =
|
15
|
-
data_request.
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
Profile::Entry.expects(:parse).with(xml).returns(entries)
|
22
|
-
|
23
|
-
profiles = []
|
24
|
-
entries.each do |entry|
|
25
|
-
profile = stub
|
26
|
-
profiles << profile
|
27
|
-
Garb::Profile.expects(:new).with(entry, @session).returns(profile)
|
28
|
-
end
|
29
|
-
|
30
|
-
assert_equal profiles, Profile.all(@session)
|
13
|
+
|
14
|
+
data_request = stub
|
15
|
+
data_request.stubs(:send_request).returns(stub(:body => xml))
|
16
|
+
DataRequest.stubs(:new).returns(data_request)
|
17
|
+
|
18
|
+
assert_equal ['12345', '12346'], Profile.all(@session).map(&:id)
|
19
|
+
assert_received(DataRequest, :new) {|e| e.with(@session, url)}
|
20
|
+
assert_received(data_request, :send_request)
|
31
21
|
end
|
32
22
|
|
33
23
|
should "return the first profile for a given web property id" do
|
@@ -35,11 +25,11 @@ module Garb
|
|
35
25
|
profile2 = stub(:web_property_id => '67890', :id => 'ghijkl')
|
36
26
|
entries = [profile1, profile2]
|
37
27
|
|
38
|
-
|
28
|
+
Profile.stubs(:all).returns(entries)
|
39
29
|
|
40
|
-
assert_equal profile1,
|
30
|
+
assert_equal profile1, Profile.first('12345', @session)
|
41
31
|
|
42
|
-
assert_received(
|
32
|
+
assert_received(Profile, :all) {|e| e.with(@session)}
|
43
33
|
end
|
44
34
|
|
45
35
|
should "return the first profile for a given table id" do
|
@@ -47,41 +37,39 @@ module Garb
|
|
47
37
|
profile2 = stub(:id => '67890', :web_property_id => 'ghijkl')
|
48
38
|
entries = [profile1, profile2]
|
49
39
|
|
50
|
-
|
40
|
+
Profile.stubs(:all).returns(entries)
|
51
41
|
|
52
|
-
assert_equal profile2,
|
42
|
+
assert_equal profile2, Profile.first('67890', @session)
|
53
43
|
|
54
|
-
assert_received(
|
44
|
+
assert_received(Profile, :all) {|e| e.with(@session)}
|
55
45
|
end
|
56
46
|
end
|
57
47
|
|
58
48
|
context "An instance of the Profile class" do
|
59
|
-
|
60
49
|
setup do
|
61
|
-
|
62
|
-
@profile = Profile.new(
|
50
|
+
entry = Profile.parse(read_fixture('profile_feed.xml')).first
|
51
|
+
@profile = Profile.new(entry, Session)
|
63
52
|
end
|
64
53
|
|
65
54
|
should "have a value for :title" do
|
66
55
|
assert_equal "Historical", @profile.title
|
67
56
|
end
|
68
|
-
|
57
|
+
|
69
58
|
should "have a value for :table_id" do
|
70
59
|
assert_equal 'ga:12345', @profile.table_id
|
71
60
|
end
|
72
|
-
|
61
|
+
|
73
62
|
should "have a value for :id" do
|
74
63
|
assert_equal '12345', @profile.id
|
75
64
|
end
|
76
|
-
|
65
|
+
|
77
66
|
should "have a value for :account_id" do
|
78
67
|
assert_equal '1111', @profile.account_id
|
79
68
|
end
|
80
|
-
|
69
|
+
|
81
70
|
should "have a value for :account_name" do
|
82
71
|
assert_equal 'Blog Beta', @profile.account_name
|
83
72
|
end
|
84
73
|
end
|
85
|
-
|
86
74
|
end
|
87
|
-
end
|
75
|
+
end
|
@@ -2,27 +2,12 @@ require File.join(File.dirname(__FILE__), '..', '..', '/test_helper')
|
|
2
2
|
|
3
3
|
module Garb
|
4
4
|
class ReportResponseTest < MiniTest::Unit::TestCase
|
5
|
-
context "
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
end
|
10
|
-
|
11
|
-
should "parse xml response with happymapper" do
|
12
|
-
h1 = {"city"=>"(not set)", "pageviews"=>"33", "country"=>"(not set)"}
|
13
|
-
h2 = {"city"=>"Kabul", "pageviews"=>"2", "country"=>"Afghanistan"}
|
14
|
-
h3 = {"city"=>"Tirana", "pageviews"=>"1", "country"=>"Albania"}
|
15
|
-
|
16
|
-
OpenStruct.expects(:new).with(h1).returns('entry1')
|
17
|
-
OpenStruct.expects(:new).with(h2).returns('entry2')
|
18
|
-
OpenStruct.expects(:new).with(h3).returns('entry3')
|
5
|
+
context "A ReportResponse" do
|
6
|
+
should "parse results from atom xml" do
|
7
|
+
filename = File.join(File.dirname(__FILE__), '..', '..', "/fixtures/report_feed.xml")
|
8
|
+
response = ReportResponse.new(File.read(filename))
|
19
9
|
|
20
|
-
assert_equal
|
21
|
-
end
|
22
|
-
|
23
|
-
should "have results or parse them" do
|
24
|
-
@response.expects(:parse)
|
25
|
-
@response.results
|
10
|
+
assert_equal ['33', '2', '1'], response.results.map(&:pageviews)
|
26
11
|
end
|
27
12
|
end
|
28
13
|
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 7
|
8
|
-
-
|
9
|
-
version: 0.7.
|
8
|
+
- 4
|
9
|
+
version: 0.7.4
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Tony Pitale
|
@@ -15,11 +15,11 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-03-
|
18
|
+
date: 2010-03-25 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
|
-
name:
|
22
|
+
name: crack
|
23
23
|
prerelease: false
|
24
24
|
requirement: &id001 !ruby/object:Gem::Requirement
|
25
25
|
requirements:
|
@@ -27,9 +27,9 @@ dependencies:
|
|
27
27
|
- !ruby/object:Gem::Version
|
28
28
|
segments:
|
29
29
|
- 0
|
30
|
-
-
|
31
|
-
-
|
32
|
-
version: 0.
|
30
|
+
- 1
|
31
|
+
- 6
|
32
|
+
version: 0.1.6
|
33
33
|
type: :runtime
|
34
34
|
version_requirements: *id001
|
35
35
|
description:
|