garb 0.8.0 → 0.8.1

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