garb 0.8.0 → 0.8.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/lib/garb.rb CHANGED
@@ -28,6 +28,12 @@ require 'garb/report_response'
28
28
  require 'garb/resource'
29
29
  require 'garb/report'
30
30
 
31
+ # management
32
+ require 'garb/management/feed'
33
+ require 'garb/management/account'
34
+ require 'garb/management/web_property'
35
+ require 'garb/management/profile'
36
+
31
37
  require 'support'
32
38
 
33
39
  module Garb
@@ -46,4 +52,15 @@ module Garb
46
52
  thing.to_s.gsub(/^ga\:/, '').underscore
47
53
  end
48
54
  alias :from_ga :from_google_analytics
55
+
56
+ def parse_properties(entry)
57
+ entry['dxp:property'].inject({}) do |hash, p|
58
+ hash[Garb.from_ga(p['name'])] = p['value']
59
+ hash
60
+ end
61
+ end
62
+
63
+ def parse_link(entry, rel)
64
+ entry['link'].detect {|link| link["rel"] == rel}['href']
65
+ end
49
66
  end
@@ -0,0 +1,32 @@
1
+ module Garb
2
+ module Management
3
+ class Account
4
+ attr_reader :session, :path
5
+ attr_reader :id, :title, :name
6
+
7
+ def self.all(session = Session)
8
+ feed = Feed.new(session, '/accounts') # builds request and parses response
9
+
10
+ feed.entries.map {|entry| new(entry, session)}
11
+ end
12
+
13
+ def initialize(entry, session)
14
+ @session = session
15
+ @path = Garb.parse_link(entry, "self").gsub(Feed::BASE_URL, '')
16
+ @title = entry['title'].gsub('Google Analytics Account ', '')
17
+
18
+ properties = Garb.parse_properties(entry)
19
+ @id = properties["account_id"]
20
+ @name = properties["account_name"]
21
+ end
22
+
23
+ def web_properties
24
+ @web_properties ||= WebProperty.for_account(self) # will call path
25
+ end
26
+
27
+ def profiles
28
+ @profiles ||= Profile.for_account(self)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,26 @@
1
+ module Garb
2
+ module Management
3
+ class Feed
4
+ BASE_URL = "https://www.google.com/analytics/feeds/datasources/ga"
5
+
6
+ attr_reader :request
7
+
8
+ def initialize(session, path)
9
+ @request = DataRequest.new(session, BASE_URL+path)
10
+ end
11
+
12
+ def parsed_response
13
+ @parsed_response ||= Crack::XML.parse(response.body)
14
+ end
15
+
16
+ def entries
17
+ # possible to have nil entries, yuck
18
+ parsed_response ? [parsed_response['feed']['entry']].flatten.reject {|e| e.nil?} : []
19
+ end
20
+
21
+ def response
22
+ @response ||= request.send_request
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,20 @@
1
+ module Garb
2
+ class Goal
3
+ attr_reader :name, :number, :value, :destination
4
+
5
+ def initialize(attributes={})
6
+ return unless attributes.is_a?(Hash)
7
+
8
+ @name = attributes['name']
9
+ @number = attributes['number'].to_i
10
+ @value = attributes['value'].to_f
11
+ @active = (attributes['active'] == 'true')
12
+
13
+ @destination = Destination.new(attributes[Garb.to_ga('destination')])
14
+ end
15
+
16
+ def active?
17
+ @active
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,42 @@
1
+ module Garb
2
+ module Management
3
+ class Profile
4
+
5
+ include ProfileReports
6
+
7
+ attr_reader :session, :path
8
+ attr_reader :id, :title, :account_id, :web_property_id
9
+
10
+ def self.all(session = Session, path = '/accounts/~all/webproperties/~all/profiles')
11
+ feed = Feed.new(session, path)
12
+ feed.entries.map {|entry| new(entry, session)}
13
+ end
14
+
15
+ def self.for_account(account)
16
+ all(account.session, account.path+'/webproperties/~all/profiles')
17
+ end
18
+
19
+ def self.for_web_property(web_property)
20
+ all(web_property.session, web_property.path+'/profiles')
21
+ end
22
+
23
+ def initialize(entry, session)
24
+ @session = session
25
+ @path = Garb.parse_link(entry, "self").gsub(Feed::BASE_URL, '')
26
+ @title = entry['title'].gsub('Google Analytics Profile ', '')
27
+
28
+ properties = Garb.parse_properties(entry)
29
+ @id = properties['profile_id']
30
+ @account_id = properties['account_id']
31
+ @web_property_id = properties['web_property_id']
32
+ end
33
+
34
+ # def path
35
+ # ['/accounts', self.account_id, 'webproperties', self.web_property_id, 'profiles', self.id].join('/')
36
+ # end
37
+
38
+ # def goals
39
+ # end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,30 @@
1
+ module Garb
2
+ module Management
3
+ class WebProperty
4
+ attr_reader :session, :path
5
+ attr_reader :id, :account_id
6
+
7
+ def self.all(session = Session, path='/accounts/~all/webproperties')
8
+ feed = Feed.new(session, path)
9
+ feed.entries.map {|entry| new(entry, session)}
10
+ end
11
+
12
+ def self.for_account(account)
13
+ all(account.session, account.path+'/webproperties')
14
+ end
15
+
16
+ def initialize(entry, session)
17
+ @session = session
18
+ @path = Garb.parse_link(entry, "self").gsub(Feed::BASE_URL, '')
19
+
20
+ properties = Garb.parse_properties(entry)
21
+ @id = properties["web_property_id"]
22
+ @account_id = properties["account_id"]
23
+ end
24
+
25
+ def profiles
26
+ @profiles ||= Profile.for_web_property(self)
27
+ end
28
+ end
29
+ end
30
+ end
data/lib/garb/profile.rb CHANGED
@@ -11,8 +11,8 @@ module Garb
11
11
  @table_id = entry['dxp:tableId']
12
12
  @goals = (entry[Garb.to_ga('goal')] || []).map {|g| Goal.new(g)}
13
13
 
14
- entry['dxp:property'].each do |p|
15
- instance_variable_set :"@#{Garb.from_ga(p['name'])}", p['value']
14
+ Garb.parse_properties(entry).each do |k,v|
15
+ instance_variable_set :"@#{k}", v
16
16
  end
17
17
  end
18
18
 
@@ -24,6 +24,7 @@ module Garb
24
24
  AccountFeedRequest.new(session).entries.map {|entry| new(entry, session)}
25
25
  end
26
26
 
27
+ # ActiveSupport::Deprecation.warn
27
28
  def self.first(id, session = Session)
28
29
  all(session).detect {|profile| profile.id == id || profile.web_property_id == id }
29
30
  end
data/lib/garb/resource.rb CHANGED
@@ -44,6 +44,18 @@ module Garb
44
44
  @segment = "gaid::#{id.to_i}"
45
45
  end
46
46
 
47
+ def segment
48
+ @segment
49
+ end
50
+
51
+ def set_instance_klass(klass)
52
+ @instance_klass = klass
53
+ end
54
+
55
+ def instance_klass
56
+ @instance_klass || OpenStruct
57
+ end
58
+
47
59
  def results(profile, opts = {}, &block)
48
60
  @profile = profile.is_a?(Profile) ? profile : Profile.first(profile, opts.fetch(:session, Session))
49
61
 
@@ -55,7 +67,7 @@ module Garb
55
67
 
56
68
  instance_eval(&block) if block_given?
57
69
 
58
- ReportResponse.new(send_request_for_body).results
70
+ ReportResponse.new(send_request_for_body, instance_klass).results
59
71
  else
60
72
  []
61
73
  end
@@ -72,7 +84,7 @@ module Garb
72
84
  end
73
85
 
74
86
  def segment_params
75
- @segment ? {'segment' => @segment} : {}
87
+ segment.nil? ? {} : {'segment' => segment}
76
88
  end
77
89
 
78
90
  def params
data/lib/garb/version.rb CHANGED
@@ -3,7 +3,7 @@ module Garb
3
3
 
4
4
  MAJOR = 0
5
5
  MINOR = 8
6
- TINY = 0
6
+ TINY = 1
7
7
 
8
8
  def self.to_s # :nodoc:
9
9
  [MAJOR, MINOR, TINY].join('.')
@@ -0,0 +1,54 @@
1
+ require 'test_helper'
2
+
3
+ module Garb
4
+ module Management
5
+ class AccountTest < MiniTest::Unit::TestCase
6
+ context "The Account class" do
7
+ should "turn entries for path into array of accounts" do
8
+ feed = stub(:entries => ["entry1"])
9
+ Feed.stubs(:new).returns(feed)
10
+
11
+ Account.stubs(:new)
12
+ Account.all
13
+
14
+ assert_received(Feed, :new) {|e| e.with(Session, '/accounts')}
15
+ assert_received(feed, :entries)
16
+ assert_received(Account, :new) {|e| e.with("entry1", Session)}
17
+ end
18
+ end
19
+
20
+ context "an Account" do
21
+ setup do
22
+ entry = {
23
+ "title" => "Google Analytics Account Garb",
24
+ "link" => [{"rel" => "self", "href" => Feed::BASE_URL+"/accounts/123456"}],
25
+ "dxp:property" => [
26
+ {"name" => "ga:accountId", "value" => "123456"},
27
+ {"name" => "ga:accountName", "value" => "Garb"}
28
+ ]
29
+ }
30
+ @account = Account.new(entry, Session)
31
+ end
32
+
33
+ should "extract id and title from GA entry" do
34
+ assert_equal "Garb", @account.title
35
+ assert_equal "123456", @account.id
36
+ end
37
+
38
+ should "extract a name from GA entry properties" do
39
+ assert_equal "Garb", @account.name
40
+ end
41
+
42
+ should "combine the Account.path and the id into an new path" do
43
+ assert_equal "/accounts/123456", @account.path
44
+ end
45
+
46
+ should "have a reference to the session it was created with" do
47
+ assert_equal Session, @account.session
48
+ end
49
+
50
+ should "have web properties"
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,59 @@
1
+ require 'test_helper'
2
+
3
+ module Garb
4
+ module Management
5
+ class ProfileTest < MiniTest::Unit::TestCase
6
+ context "The Profile class" do
7
+ should "turn entries for path into array of profile" do
8
+ feed = stub(:entries => ["entry1"])
9
+ Feed.stubs(:new).returns(feed)
10
+
11
+ Profile.stubs(:new)
12
+ Profile.all
13
+
14
+ assert_received(Feed, :new) {|e| e.with(Session, '/accounts/~all/webproperties/~all/profiles')}
15
+ assert_received(feed, :entries)
16
+ assert_received(Profile, :new) {|e| e.with("entry1", Session)}
17
+ end
18
+
19
+ should "find all web properties for a given account"
20
+ should "find all web properties for a given web_property"
21
+ end
22
+
23
+ context "A Profile" do
24
+ setup do
25
+ entry = {
26
+ "title" => "Google Analytics Profile example.com",
27
+ "link" => [{"rel" => "self", "href" => Feed::BASE_URL+"/accounts/1189765/webproperties/UA-1189765-1/profiles/98765"}],
28
+ "dxp:property" => [
29
+ {"name" => "ga:profileId", "value" => "98765"},
30
+ {"name" => "ga:accountId", "value" => "1189765"},
31
+ {"name" => "ga:webPropertyId", "value" => 'UA-1189765-1'}
32
+ ]
33
+ }
34
+ @profile = Profile.new(entry, Session)
35
+ end
36
+
37
+ should "have a title" do
38
+ assert_equal "example.com", @profile.title
39
+ end
40
+
41
+ should "have an id" do
42
+ assert_equal '98765', @profile.id
43
+ end
44
+
45
+ should "have an account_id" do
46
+ assert_equal '1189765', @profile.account_id
47
+ end
48
+
49
+ should "have a web_property_id" do
50
+ assert_equal 'UA-1189765-1', @profile.web_property_id
51
+ end
52
+
53
+ should "have a path" do
54
+ assert_equal "/accounts/1189765/webproperties/UA-1189765-1/profiles/98765", @profile.path
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,58 @@
1
+ require 'test_helper'
2
+
3
+ module Garb
4
+ module Management
5
+ class WebPropertyTest < MiniTest::Unit::TestCase
6
+ context "the WebProperty class" do
7
+ should "turn entries for path into array of web properties" do
8
+ feed = stub(:entries => ["entry1"])
9
+ Feed.stubs(:new).returns(feed)
10
+
11
+ WebProperty.stubs(:new)
12
+ WebProperty.all
13
+
14
+ assert_received(Feed, :new) {|e| e.with(Session, '/accounts/~all/webproperties')}
15
+ assert_received(feed, :entries)
16
+ assert_received(WebProperty, :new) {|e| e.with("entry1", Session)}
17
+ end
18
+
19
+ should "find all web properties for a given account" do
20
+ WebProperty.stubs(:all)
21
+ WebProperty.for_account(stub(:session => Session, :path => '/accounts/123456'))
22
+
23
+ assert_received(WebProperty, :all) do |e|
24
+ e.with(Session, '/accounts/123456/webproperties')
25
+ end
26
+ end
27
+ end
28
+
29
+ context "a WebProperty" do
30
+ setup do
31
+ entry = {
32
+ "link" => [{"rel" => "self", "href" => Feed::BASE_URL+"/accounts/1189765/webproperties/UA-1189765-1"}],
33
+ "dxp:property" => [
34
+ {"name" => "ga:accountId", "value" => "1189765"},
35
+ {"name" => "ga:webPropertyId", "value" => 'UA-1189765-1'}
36
+ ]
37
+ }
38
+
39
+ @web_property = WebProperty.new(entry, Session)
40
+ end
41
+
42
+ should "have an id" do
43
+ assert_equal "UA-1189765-1", @web_property.id
44
+ end
45
+
46
+ should "have an account_id" do
47
+ assert_equal "1189765", @web_property.account_id
48
+ end
49
+
50
+ should "have profiles" do
51
+ Profile.stubs(:for_web_property)
52
+ @web_property.profiles
53
+ assert_received(Profile, :for_web_property) {|e| e.with(@web_property)}
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -11,7 +11,7 @@ class ResourceTest < MiniTest::Unit::TestCase
11
11
  should "get results from GA" do
12
12
  profile = stub(:is_a? => true)
13
13
  TestReport.expects(:send_request_for_body).returns('xml')
14
- Garb::ReportResponse.expects(:new).with('xml').returns(mock(:results => 'analytics'))
14
+ Garb::ReportResponse.expects(:new).with('xml', OpenStruct).returns(mock(:results => 'analytics'))
15
15
 
16
16
  assert_equal 'analytics', TestReport.results(profile)
17
17
  end
@@ -20,12 +20,23 @@ class ResourceTest < MiniTest::Unit::TestCase
20
20
  profile = '123'
21
21
  session = Garb::Session.new
22
22
  TestReport.expects(:send_request_for_body).returns('xml')
23
- Garb::ReportResponse.expects(:new).with('xml').returns(mock(:results => 'analytics'))
23
+ Garb::ReportResponse.expects(:new).with('xml', OpenStruct).returns(mock(:results => 'analytics'))
24
24
  Garb::Profile.expects(:first).with(profile, session).returns(mock('Garb::Profile'))
25
25
 
26
26
  assert_equal 'analytics', TestReport.results(profile, :session => session)
27
27
  end
28
28
 
29
+ should "permit setting a segment id" do
30
+ TestReport.set_segment_id 1
31
+ assert_equal "gaid::1", TestReport.segment
32
+ end
33
+
34
+ should "permit setting a klass used for instantiation of results" do
35
+ TestKlass = Class.new(OpenStruct)
36
+ TestReport.set_instance_klass TestKlass
37
+ assert_equal TestKlass, TestReport.instance_klass
38
+ end
39
+
29
40
  should "return an empty result set if profile is invalid" do
30
41
  profile = '123'
31
42
  TestReport.expects(:send_request_for_body).never
@@ -10,5 +10,17 @@ class GarbTest < MiniTest::Unit::TestCase
10
10
  should 'remove ga: prefix' do
11
11
  assert_equal 'bob', Garb.from_google_analytics('ga:bob')
12
12
  end
13
+
14
+ should "have a helper to parse properties out of entries" do
15
+ entry = {"dxp:property"=>[{"name"=>"ga:accountId", "value"=>"1189765"}, {"name"=>"ga:webPropertyId", "value"=>"UA-1189765-1"}]}
16
+
17
+ assert_equal({"account_id" => '1189765', "web_property_id" => "UA-1189765-1"}, Garb.parse_properties(entry))
18
+ end
19
+
20
+ should "parse out the self link" do
21
+ entry = {"link" => [{"rel" => "self", "href" => "http://google.com/accounts/12345"}]}
22
+
23
+ assert_equal "http://google.com/accounts/12345", Garb.parse_link(entry, "self")
24
+ end
13
25
  end
14
26
  end
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: garb
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 61
4
5
  prerelease: false
5
6
  segments:
6
7
  - 0
7
8
  - 8
8
- - 0
9
- version: 0.8.0
9
+ - 1
10
+ version: 0.8.1
10
11
  platform: ruby
11
12
  authors:
12
13
  - Tony Pitale
@@ -14,34 +15,40 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2010-09-08 00:00:00 -04:00
18
+ date: 2010-10-09 00:00:00 -04:00
18
19
  default_executable:
19
20
  dependencies:
20
21
  - !ruby/object:Gem::Dependency
21
- name: activesupport
22
+ name: crack
23
+ prerelease: false
22
24
  requirement: &id001 !ruby/object:Gem::Requirement
23
25
  none: false
24
26
  requirements:
25
27
  - - ">="
26
28
  - !ruby/object:Gem::Version
29
+ hash: 23
27
30
  segments:
28
31
  - 0
29
- version: "0"
32
+ - 1
33
+ - 6
34
+ version: 0.1.6
30
35
  type: :runtime
31
- prerelease: false
32
36
  version_requirements: *id001
33
37
  - !ruby/object:Gem::Dependency
34
- name: crack
38
+ name: activesupport
39
+ prerelease: false
35
40
  requirement: &id002 !ruby/object:Gem::Requirement
36
41
  none: false
37
42
  requirements:
38
43
  - - ">="
39
44
  - !ruby/object:Gem::Version
45
+ hash: 7
40
46
  segments:
47
+ - 2
48
+ - 2
41
49
  - 0
42
- version: "0"
50
+ version: 2.2.0
43
51
  type: :runtime
44
- prerelease: false
45
52
  version_requirements: *id002
46
53
  description:
47
54
  email: tony.pitale@viget.com
@@ -61,6 +68,11 @@ files:
61
68
  - lib/garb/destination.rb
62
69
  - lib/garb/filter_parameters.rb
63
70
  - lib/garb/goal.rb
71
+ - lib/garb/management/account.rb
72
+ - lib/garb/management/feed.rb
73
+ - lib/garb/management/goal.rb
74
+ - lib/garb/management/profile.rb
75
+ - lib/garb/management/web_property.rb
64
76
  - lib/garb/profile.rb
65
77
  - lib/garb/profile_reports.rb
66
78
  - lib/garb/report.rb
@@ -89,6 +101,9 @@ files:
89
101
  - test/unit/garb/destination_test.rb
90
102
  - test/unit/garb/filter_parameters_test.rb
91
103
  - test/unit/garb/goal_test.rb
104
+ - test/unit/garb/management/account_test.rb
105
+ - test/unit/garb/management/profile_test.rb
106
+ - test/unit/garb/management/web_property_test.rb
92
107
  - test/unit/garb/oauth_session_test.rb
93
108
  - test/unit/garb/profile_reports_test.rb
94
109
  - test/unit/garb/profile_test.rb
@@ -114,6 +129,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
114
129
  requirements:
115
130
  - - ">="
116
131
  - !ruby/object:Gem::Version
132
+ hash: 3
117
133
  segments:
118
134
  - 0
119
135
  version: "0"
@@ -122,6 +138,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
122
138
  requirements:
123
139
  - - ">="
124
140
  - !ruby/object:Gem::Version
141
+ hash: 3
125
142
  segments:
126
143
  - 0
127
144
  version: "0"
@@ -144,6 +161,9 @@ test_files:
144
161
  - test/unit/garb/destination_test.rb
145
162
  - test/unit/garb/filter_parameters_test.rb
146
163
  - test/unit/garb/goal_test.rb
164
+ - test/unit/garb/management/account_test.rb
165
+ - test/unit/garb/management/profile_test.rb
166
+ - test/unit/garb/management/web_property_test.rb
147
167
  - test/unit/garb/oauth_session_test.rb
148
168
  - test/unit/garb/profile_reports_test.rb
149
169
  - test/unit/garb/profile_test.rb