vigetlabs-garb 0.1.2 → 0.2.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  garb
2
2
  ====
3
3
 
4
- by Tony Pitale and Justin Marney
4
+ by Tony Pitale with much help from Justin Marney, Patrick Reagan and others at Viget Labs
5
5
 
6
6
  http://github.com/vigetlabs/garb
7
7
 
@@ -26,20 +26,14 @@ Profiles
26
26
  > Garb::Profile.all
27
27
  > profile = Garb::Profile.all.first
28
28
 
29
- Define a Report Class
30
- ---------------------
31
-
32
- class ExitsReport < Garb::Report
33
- def initialize(profile)
34
- super(profile) do |config|
35
- config.start_date = Time.now.at_beginning_of_month
36
- config.end_date = Time.now.at_end_of_month
37
- config.metrics << [:exits, :pageviews, :exit_rate]
38
- config.dimensions << :request_uri
39
- config.sort << :exits.desc
40
- config.max_results = 10
41
- end
42
- end
29
+ Define a Report Class and Get Results
30
+ -------------------------------------
31
+
32
+ class Exits
33
+ include Garb::Resource
34
+
35
+ metrics :exits, :pageviews, :exit_rate
36
+ dimensions :request_uri
43
37
  end
44
38
 
45
39
  Parameters
@@ -47,7 +41,8 @@ Parameters
47
41
 
48
42
  * start_date: The date of the period you would like this report to start
49
43
  * end_date: The date to end, inclusive
50
- * max_results: The maximum number of results to be returned
44
+ * limit: The maximum number of results to be returned
45
+ * offset: The starting index
51
46
 
52
47
  Metrics & Dimensions
53
48
  --------------------
@@ -65,13 +60,20 @@ Sorting
65
60
  -------
66
61
 
67
62
  Sorting can be done on any metric or dimension defined in the request, with .desc reversing the sort.
68
-
63
+
69
64
  Building a Report
70
65
  -----------------
71
66
 
72
- Given the class, session, and profile from above:
67
+ Given the class, session, and profile from above we can do:
73
68
 
74
- reports = ExitsReport.new(profile).all
69
+ Exits.results(profile, :limit => 10, :offset => 19)
70
+
71
+ Or, with sorting and filters:
72
+
73
+ Exits.results(profile, :limit => 10, :offset => 19) do
74
+ filter :request_uri.contains => 'season', :exits.gt => 100
75
+ sort :exits
76
+ end
75
77
 
76
78
  reports will be an array of OpenStructs with methods for the metrics and dimensions returned.
77
79
 
@@ -79,10 +81,13 @@ Build a One-Off Report
79
81
  ----------------------
80
82
 
81
83
  report = Garb::Report.new(profile)
82
- report.metrics << :pageviews
83
- report.dimensions << :request_uri
84
+ report.metrics :pageviews
85
+ report.dimensions :request_uri
86
+
87
+ report.filter :request_uri.contains => 'season', :exits.gte => 10
88
+ report.sort :exits
84
89
 
85
- report.all
90
+ report.results
86
91
 
87
92
  Filtering
88
93
  ---------
@@ -125,8 +130,6 @@ TODOS
125
130
  * Sessions are currently global, which isn't awesome
126
131
  * Single user login is the only supported method currently.
127
132
  Intend to add hooks for using OAuth
128
- * Intend to make defined report classes before more like AR
129
- * Support start-index
130
133
  * Read opensearch header in results
131
134
  * OR joining filter parameters
132
135
 
data/Rakefile CHANGED
@@ -1,26 +1,50 @@
1
- # Look in the tasks/setup.rb file for the various options that can be
2
- # configured in this Rakefile. The .rake files in the tasks directory
3
- # are where the options are used.
4
-
5
- begin
6
- require 'bones'
7
- Bones.setup
8
- rescue LoadError
9
- load 'tasks/setup.rb'
1
+ require 'rubygems'
2
+ require 'rake/gempackagetask'
3
+ require 'rake/testtask'
4
+ require 'rcov/rcovtask'
5
+
6
+ require 'lib/garb'
7
+
8
+ task :default => :test
9
+
10
+ spec = Gem::Specification.new do |s|
11
+ s.name = 'garb'
12
+ s.version = Garb::Version.to_s
13
+ s.has_rdoc = false
14
+ s.summary = "Google Analytics API Ruby Wrapper"
15
+ s.authors = ['Tony Pitale','Justin Marney', 'Patrick Reagan']
16
+ s.email = 'tony.pitale@viget.com'
17
+ s.homepage = 'http://github.com/vigetlabs/garb'
18
+ s.files = %w(README.md Rakefile) + Dir.glob("lib/**/*")
19
+ s.test_files = Dir.glob("test/**/*")
20
+
21
+ s.add_dependency("jnunemaker-happymapper", [">= 0.2.2"])
22
+ s.add_dependency("libxml-ruby", [">= 0.9.8"])
10
23
  end
11
24
 
12
- ensure_in_path 'lib'
13
- require 'garb'
25
+ Rake::GemPackageTask.new(spec) do |pkg|
26
+ pkg.gem_spec = spec
27
+ end
14
28
 
15
- task :default => 'test'
29
+ Rake::TestTask.new do |t|
30
+ t.libs << 'test'
31
+ t.test_files = FileList["test/**/*_test.rb"]
32
+ t.verbose = true
33
+ end
34
+
35
+ desc 'Generate the gemspec to serve this Gem from Github'
36
+ task :github do
37
+ file = File.dirname(__FILE__) + "/#{spec.name}.gemspec"
38
+ File.open(file, 'w') {|f| f << spec.to_ruby }
39
+ puts "Created gemspec: #{file}"
40
+ end
16
41
 
17
- PROJ.name = 'garb'
18
- PROJ.authors = ['Tony Pitale','Justin Marney']
19
- PROJ.email = 'tony.pitale@viget.com'
20
- PROJ.url = 'http://github.com/vigetlabs/garb'
21
- PROJ.version = Garb::VERSION
22
- PROJ.rubyforge.name = 'garb'
23
- PROJ.test.files = FileList['test/**/*_test.rb']
24
- PROJ.spec.opts << '--color'
42
+ desc "Generate RCov coverage report"
43
+ Rcov::RcovTask.new(:rcov) do |t|
44
+ t.test_files = FileList['test/**/*_test.rb']
45
+ t.rcov_opts << "-x lib/garb.rb -x lib/garb/version.rb"
46
+ end
47
+
48
+ task :default => 'test'
25
49
 
26
50
  # EOF
@@ -1,20 +1,20 @@
1
1
  module Garb
2
2
  class DataRequest
3
-
3
+
4
4
  def initialize(base_url, parameters={})
5
5
  @base_url = base_url
6
6
  @parameters = parameters
7
7
  end
8
-
8
+
9
9
  def query_string
10
10
  parameter_list = @parameters.map {|k,v| "#{k}=#{v}" }
11
11
  parameter_list.empty? ? '' : "?#{parameter_list.join('&')}"
12
12
  end
13
-
13
+
14
14
  def uri
15
15
  URI.parse(@base_url)
16
16
  end
17
-
17
+
18
18
  def send_request
19
19
  http = Net::HTTP.new(uri.host, uri.port)
20
20
  http.use_ssl = true
@@ -23,6 +23,6 @@ module Garb
23
23
  raise response.body.inspect unless response.is_a?(Net::HTTPOK)
24
24
  response
25
25
  end
26
-
26
+
27
27
  end
28
28
  end
@@ -0,0 +1,21 @@
1
+ module Garb
2
+ class OAuthSession
3
+ attr_accessor :access_token
4
+
5
+ OAuthGetRequestToken = "https://www.google.com/accounts/OAuthGetRequestToken"
6
+ OAuthAuthorizeToken = "https://www.google.com/accounts/OAuthAuthorizeToken"
7
+ OAuthGetAccessToken = "https://www.google.com/accounts/OAuthGetAccessToken"
8
+
9
+ def get_request_token
10
+
11
+ end
12
+
13
+ def authorization_request
14
+
15
+ end
16
+
17
+ def get_access_token
18
+
19
+ end
20
+ end
21
+ end
data/lib/garb/report.rb CHANGED
@@ -1,211 +1,31 @@
1
- require 'ostruct'
2
-
3
1
  module Garb
4
2
  class Report
3
+ include Resource::ResourceMethods
4
+
5
5
  MONTH = 2592000
6
6
  URL = "https://www.google.com/analytics/feeds/data"
7
7
 
8
- METRICS = {
9
- :visitor => [
10
- :avgPageviews,
11
- :avgSessionTime,
12
- :bounces,
13
- :bounceRate,
14
- :entrances,
15
- :exits,
16
- :exitRate,
17
- :newVisitors,
18
- :pageDuration,
19
- :pageviews,
20
- :visitDuration,
21
- :visitors,
22
- :visits
23
- ],
24
- :campaign => [
25
- :cost,
26
- :clicks,
27
- :clickThroughRate,
28
- :costPerConversion,
29
- :costPerGoalConversion,
30
- :costPerMilleImpressions,
31
- :costPerTransaction,
32
- :impressions
33
- ],
34
- :content => [
35
- :uniquePageviews
36
- ],
37
- :ecommerce => [
38
- :productPurchases,
39
- :productRevenue,
40
- :products,
41
- :revenue,
42
- :revenuePerClick,
43
- :revenuePerTransaction,
44
- :revenuePerVisit,
45
- :shipping,
46
- :tax,
47
- :transactions
48
- ],
49
- :internal_search => [
50
- :searchDepth,
51
- :searchDuration,
52
- :searchExits,
53
- :searchTransitions,
54
- :uniqueInternalSearches,
55
- :visitsWithSearches
56
- ],
57
- :goals => [
58
- :goalCompletions1,
59
- :goalCompletions2,
60
- :goalCompletions3,
61
- :goalCompletions4,
62
- :goalCompletionsAll,
63
- :goalConversionRate,
64
- :goalStarts1,
65
- :goalStarts2,
66
- :goalStarts3,
67
- :goalStarts4,
68
- :goalStartsAll,
69
- :goalValue1,
70
- :goalValue2,
71
- :goalValue3,
72
- :goalValue4,
73
- :goalValueAll,
74
- :goalValuePerVisit
75
- ]
76
- }
77
-
78
- DIMENSIONS = {
79
- :visitor => [
80
- :browser,
81
- :browserVersion,
82
- :city,
83
- :connectionSpeed,
84
- :continent,
85
- :country,
86
- :daysSinceLastVisit,
87
- :domain,
88
- :flashVersion,
89
- :hostname,
90
- :hour,
91
- :javaEnabled,
92
- :languqage,
93
- :medium,
94
- :organization,
95
- :pageDepth,
96
- :platform,
97
- :platformVersion,
98
- :referralPath,
99
- :region,
100
- :screenColors,
101
- :screenResolution,
102
- :subContinentRegion,
103
- :userDefinedValue,
104
- :visitNumber,
105
- :visitorType
106
- ],
107
- :campaign => [
108
- :adGroup,
109
- :adSlot,
110
- :adSlotPosition,
111
- :campaign,
112
- :content,
113
- :keyword,
114
- :source,
115
- :sourceMedium
116
- ],
117
- :content => [
118
- :pageTitle,
119
- :requestUri,
120
- :requestUri1,
121
- :requestUriLast
122
- ],
123
- :ecommerce => [
124
- :affiliation,
125
- :daysToTransaction,
126
- :productCode,
127
- :productName,
128
- :productVariation,
129
- :transactionId,
130
- :visitsToTransaction
131
- ],
132
- :internal_search => [
133
- :hasInternalSearch,
134
- :internalSearchKeyword,
135
- :internalSearchNext,
136
- :internalSearchType
137
- ]
138
- }
139
-
140
- attr_accessor :metrics, :dimensions, :sort, :filters,
141
- :start_date, :max_results, :end_date
142
-
143
- attr_reader :profile
144
-
145
- # def self.element_id(property_name)
146
- # property_name.is_a?(Operator) ? property_name.to_s : property_name.to_ga.lower_camelized
147
- # end
148
- #
149
- # def self.property_value(entry, property_name)
150
- # (entry/property_name).first.inner_text
151
- # end
152
- #
153
- # def self.property_values(entry, property_names)
154
- # hash = property_names.inject({}) do |hash, property_name|
155
- # hash.merge({property_name => property_value(entry, property_name.to_s.lower_camelized)})
156
- # end
157
- # OpenStruct.new hash
158
- # end
159
- #
160
- def self.format_time(t)
161
- t.strftime('%Y-%m-%d')
162
- end
163
-
164
8
  def initialize(profile, opts={})
165
9
  @profile = profile
166
10
 
167
- @sort = ReportParameter.new(:sort) << opts.fetch(:sort, [])
168
- @filters = ReportParameter.new(:filters) << opts.fetch(:filters, [])
169
- @metrics = ReportParameter.new(:metrics) << opts.fetch(:metrics, [])
170
- @dimensions = ReportParameter.new(:dimensions) << opts.fetch(:dimensions, [])
171
-
172
11
  @start_date = opts.fetch(:start_date, Time.now - MONTH)
173
12
  @end_date = opts.fetch(:end_date, Time.now)
174
-
175
- yield self if block_given?
176
- end
13
+ @limit = opts.fetch(:limit, nil)
14
+ @offset = opts.fetch(:offset, nil)
177
15
 
178
- def page_params
179
- max_results.nil? ? {} : {'max-results' => max_results}
180
- end
181
-
182
- def default_params
183
- {'ids' => profile.table_id,
184
- 'start-date' => self.class.format_time(start_date),
185
- 'end-date' => self.class.format_time(end_date)}
186
- end
187
-
188
- def params
189
- [
190
- metrics.to_params,
191
- dimensions.to_params,
192
- sort.to_params,
193
- filters.to_params,
194
- page_params
195
- ].inject(default_params) do |p, i|
196
- p.merge(i)
197
- end
198
- end
199
-
200
- def send_request_for_body
201
- request = DataRequest.new(URL, params)
202
- response = request.send_request
203
- response.body
16
+ # clear filters and sort
17
+ @filters = ReportParameter.new(:filters)
18
+ @sorts = ReportParameter.new(:sort)
19
+
20
+ metrics opts.fetch(:metrics, [])
21
+ dimensions opts.fetch(:dimensions, [])
22
+ filter opts.fetch(:filter, [])
23
+ sort opts.fetch(:sort, [])
204
24
  end
205
-
206
- def all
207
- @entries = ReportResponse.new(send_request_for_body).parse
25
+
26
+ def results
27
+ ReportResponse.new(send_request_for_body).results
208
28
  end
209
-
29
+
210
30
  end
211
- end
31
+ end
@@ -13,7 +13,7 @@ module Garb
13
13
  end
14
14
 
15
15
  def <<(element)
16
- @elements += [element].flatten
16
+ (@elements += [element].flatten).compact!
17
17
  self
18
18
  end
19
19
 
@@ -23,7 +23,7 @@ module Garb
23
23
  when Hash
24
24
  elem.collect do |k,v|
25
25
  next unless k.is_a?(Operator)
26
- "#{k.target}#{CGI::escape(k.operator.to_s)}#{CGI::escape(v.to_s)}"
26
+ "#{k.target}#{URI.encode(k.operator.to_s, /[=<>]/)}#{CGI::escape(v.to_s)}"
27
27
  end.join(';')
28
28
  else
29
29
  elem.to_ga
@@ -31,6 +31,6 @@ module Garb
31
31
  end.join(',')
32
32
 
33
33
  params.empty? ? {} : {self.name => params}
34
- end
34
+ end
35
35
  end
36
36
  end
@@ -1,5 +1,7 @@
1
1
  module Garb
2
2
  class ReportResponse
3
+ # include Enumerable
4
+
3
5
  def initialize(response_body)
4
6
  @xml = response_body
5
7
  end
@@ -7,7 +9,7 @@ module Garb
7
9
  def parse
8
10
  entries = Entry.parse(@xml)
9
11
 
10
- entries.collect do |entry|
12
+ @results = entries.collect do |entry|
11
13
  hash = {}
12
14
 
13
15
  entry.metrics.each do |m|
@@ -23,6 +25,10 @@ module Garb
23
25
  OpenStruct.new(hash)
24
26
  end
25
27
  end
28
+
29
+ def results
30
+ @results || parse
31
+ end
26
32
 
27
33
  class Metric
28
34
  include HappyMapper
@@ -0,0 +1,89 @@
1
+ module Garb
2
+ module Resource
3
+ MONTH = 2592000
4
+ URL = "https://www.google.com/analytics/feeds/data"
5
+
6
+ def self.included(report)
7
+ report.extend(ResourceMethods)
8
+ end
9
+
10
+ module ResourceMethods
11
+
12
+ def metrics(*fields)
13
+ @metrics ||= ReportParameter.new(:metrics)
14
+ @metrics << fields
15
+ end
16
+
17
+ def dimensions(*fields)
18
+ @dimensions ||= ReportParameter.new(:dimensions)
19
+ @dimensions << fields
20
+ end
21
+
22
+ def filter(*hash)
23
+ @filters << hash
24
+ end
25
+
26
+ def filters
27
+ @filters ||= ReportParameter.new(:filters)
28
+ end
29
+
30
+ def sort(*fields)
31
+ @sorts << fields
32
+ end
33
+
34
+ def sorts
35
+ @sorts ||= ReportParameter.new(:sort)
36
+ end
37
+
38
+ def results(profile, opts = {}, &block)
39
+ @profile = profile
40
+
41
+ # clear filters and sort
42
+ @filters = ReportParameter.new(:filters)
43
+ @sorts = ReportParameter.new(:sort)
44
+
45
+ @start_date = opts.fetch(:start_date, Time.now - MONTH)
46
+ @end_date = opts.fetch(:end_date, Time.now)
47
+ @limit = opts.fetch(:limit, nil)
48
+ @offset = opts.fetch(:offset, nil)
49
+
50
+ instance_eval(&block) if block_given?
51
+
52
+ ReportResponse.new(send_request_for_body).results
53
+ end
54
+
55
+ def page_params
56
+ {'max-results' => @limit, 'start-index' => @offset}.reject{|k,v| v.nil?}
57
+ end
58
+
59
+ def default_params
60
+ {'ids' => @profile.table_id,
61
+ 'start-date' => format_time(@start_date),
62
+ 'end-date' => format_time(@end_date)}
63
+ end
64
+
65
+ def params
66
+ [
67
+ metrics.to_params,
68
+ dimensions.to_params,
69
+ sorts.to_params,
70
+ filters.to_params,
71
+ page_params
72
+ ].inject(default_params) do |p, i|
73
+ p.merge(i)
74
+ end
75
+ end
76
+
77
+ def format_time(t)
78
+ t.strftime('%Y-%m-%d')
79
+ end
80
+
81
+ def send_request_for_body
82
+ request = DataRequest.new(URL, params)
83
+ response = request.send_request
84
+ response.body
85
+ end
86
+
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,13 @@
1
+ module Garb
2
+ module Version
3
+
4
+ MAJOR = 0
5
+ MINOR = 2
6
+ TINY = 0
7
+
8
+ def self.to_s # :nodoc:
9
+ [MAJOR, MINOR, TINY].join('.')
10
+ end
11
+
12
+ end
13
+ end
data/lib/garb.rb CHANGED
@@ -4,15 +4,18 @@ require 'net/http'
4
4
  require 'net/https'
5
5
  require 'rubygems'
6
6
  require 'cgi'
7
+ require 'ostruct'
7
8
  require 'happymapper'
8
9
 
10
+ require 'garb/version'
9
11
  require 'garb/authentication_request'
10
12
  require 'garb/data_request'
11
13
  require 'garb/session'
12
14
  require 'garb/profile'
13
- require 'garb/report'
14
15
  require 'garb/report_parameter'
15
16
  require 'garb/report_response'
17
+ require 'garb/resource'
18
+ require 'garb/report'
16
19
 
17
20
  require 'extensions/string'
18
21
  require 'extensions/operator'
data/test/test_helper.rb CHANGED
@@ -1,8 +1,11 @@
1
- require 'test/unit'
1
+ $:.reject! { |e| e.include? 'TextMate' }
2
+
2
3
  require 'rubygems'
3
- require 'mocha'
4
+ require 'test/unit'
4
5
  require 'shoulda'
5
- require 'garb'
6
+ require 'mocha'
7
+
8
+ require File.dirname(__FILE__) + '/../lib/garb'
6
9
 
7
10
  class Test::Unit::TestCase
8
11
 
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/test_helper'
1
+ require File.join(File.dirname(__FILE__), '..', '/test_helper')
2
2
 
3
3
  module Garb
4
4
  class AuthenticationRequestTest < Test::Unit::TestCase
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), 'test_helper')
1
+ require File.join(File.dirname(__FILE__), '..', '/test_helper')
2
2
 
3
3
  module Garb
4
4
  class DataRequestTest < Test::Unit::TestCase
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), 'test_helper')
1
+ require File.join(File.dirname(__FILE__), '..', '/test_helper')
2
2
 
3
3
  class GarbTest < Test::Unit::TestCase
4
4
  context "A green egg" do
@@ -0,0 +1,11 @@
1
+ require File.join(File.dirname(__FILE__), '..', '/test_helper')
2
+
3
+ module Garb
4
+ class OAuthSessionTest < Test::Unit::TestCase
5
+ context "An instance of OAuthSession" do
6
+ should "have tests" do
7
+ assert true
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), 'test_helper')
1
+ require File.join(File.dirname(__FILE__), '..', '/test_helper')
2
2
 
3
3
  class OperatorTest < Test::Unit::TestCase
4
4
  context "An instance of an Operator" do
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), 'test_helper')
1
+ require File.join(File.dirname(__FILE__), '..', '/test_helper')
2
2
 
3
3
  module Garb
4
4
  class ProfileTest < Test::Unit::TestCase
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), 'test_helper')
1
+ require File.join(File.dirname(__FILE__), '..', '/test_helper')
2
2
 
3
3
  module Garb
4
4
  class ReportParameterTest < Test::Unit::TestCase
@@ -45,7 +45,14 @@ module Garb
45
45
  should "parameterize hash operators and join elements" do
46
46
  @metrics << {:city.eql => 'New York'}
47
47
  params = {'metrics' => 'ga:city%3D%3DNew+York'}
48
-
48
+
49
+ assert_equal params, @metrics.to_params
50
+ end
51
+
52
+ should "properly encode operators" do
53
+ @metrics << {:request_uri.contains => 'New York'}
54
+ params = {'metrics' => 'ga:requestUri%3D~New+York'}
55
+
49
56
  assert_equal params, @metrics.to_params
50
57
  end
51
58
  end
@@ -1,10 +1,10 @@
1
- require File.join(File.dirname(__FILE__), 'test_helper')
1
+ require File.join(File.dirname(__FILE__), '..', '/test_helper')
2
2
 
3
3
  module Garb
4
4
  class ReportResponseTest < Test::Unit::TestCase
5
5
  context "An instance of the ReportResponse class" do
6
6
  setup do
7
- @xml = File.read(File.dirname(__FILE__) + "/fixtures/report_feed.xml")
7
+ @xml = File.read(File.join(File.dirname(__FILE__), '..', "/fixtures/report_feed.xml"))
8
8
  @response = ReportResponse.new(@xml)
9
9
  end
10
10
 
@@ -19,6 +19,11 @@ module Garb
19
19
 
20
20
  assert_equal(['entry1', 'entry2', 'entry3'], @response.parse)
21
21
  end
22
+
23
+ should "have results or parse them" do
24
+ @response.expects(:parse)
25
+ @response.results
26
+ end
22
27
  end
23
28
  end
24
29
  end
@@ -0,0 +1,71 @@
1
+ require File.join(File.dirname(__FILE__), '..', '/test_helper')
2
+
3
+ module Garb
4
+ # Also tests Garb::Resource, which is the basis for Garb::Report
5
+ class ReportTest < Test::Unit::TestCase
6
+ context "An instance of the Report class" do
7
+ setup do
8
+ @now = Time.now
9
+ Time.stubs(:now).returns(@now)
10
+ @profile = stub(:table_id => 'ga:1234')
11
+ @report = Report.new(@profile)
12
+ end
13
+
14
+ %w(metrics dimensions filters sorts).each do |param|
15
+ should "have parameters for #{param}" do
16
+ assert @report.send(:"#{param}").is_a?(ReportParameter)
17
+ end
18
+ end
19
+
20
+ should "have default parameters" do
21
+ @report.stubs(:format_time).returns('2009-08-01')
22
+ params = {'ids' => 'ga:1234', 'start-date' => '2009-08-01', 'end-date' => '2009-08-01'}
23
+ assert_equal params, @report.default_params
24
+ end
25
+
26
+ should "collect params from metrics, dimensions, filters, sort, and defaults" do
27
+ @report.stubs(:metrics).returns(stub(:to_params => {'metrics' => 6}))
28
+ @report.stubs(:dimensions).returns(stub(:to_params => {'dimensions' => 5}))
29
+ @report.stubs(:filters).returns(stub(:to_params => {'filters' => 4}))
30
+ @report.stubs(:sorts).returns(stub(:to_params => {'sort' => 3}))
31
+ @report.stubs(:page_params).returns({'page_params' => 2})
32
+ @report.stubs(:default_params).returns({'default_params' => 1})
33
+
34
+ params = {'metrics' => 6, 'dimensions' => 5, 'filters' => 4, 'sort' => 3, 'page_params' => 2, 'default_params' => 1}
35
+ assert_equal params, @report.params
36
+ end
37
+
38
+ should "format time" do
39
+ assert_equal @now.strftime('%Y-%m-%d'), @report.format_time(@now)
40
+ end
41
+
42
+ should "send a data request to GA" do
43
+ response = mock {|m| m.expects(:body).returns('response body') }
44
+ request = mock {|m| m.expects(:send_request).returns(response) }
45
+ @report.expects(:params).returns('params')
46
+
47
+ DataRequest.expects(:new).with(Garb::Report::URL, 'params').returns(request)
48
+ assert_equal 'response body', @report.send_request_for_body
49
+ end
50
+
51
+ should "fetch and parse results from GA" do
52
+ @report.expects(:send_request_for_body).with().returns('xml')
53
+ ReportResponse.expects(:new).with('xml').returns(mock(:results => ['entry']))
54
+ assert_equal ['entry'], @report.results
55
+ end
56
+ end
57
+
58
+ context "An instance of the Report class with initial options" do
59
+ setup do
60
+ @profile = stub(:table_id => 'ga:1234')
61
+ @report = Report.new(@profile, :limit => 10, :offset => 20)
62
+ end
63
+
64
+ should "have page paramaters" do
65
+ params = {'max-results' => 10, 'start-index' => 20}
66
+ assert_equal params, @report.page_params
67
+ end
68
+ end
69
+
70
+ end
71
+ end
@@ -0,0 +1,19 @@
1
+ require File.join(File.dirname(__FILE__), '..', '/test_helper')
2
+
3
+ class TestReport
4
+ include Garb::Resource
5
+ end
6
+
7
+ # Most of the resource testing is done as a part of ReportTest
8
+ class ResourceTest < Test::Unit::TestCase
9
+
10
+ context "A class with Garb::Resource mixed in" do
11
+ should "get results from GA" do
12
+ profile = stub
13
+ TestReport.expects(:send_request_for_body).returns('xml')
14
+ Garb::ReportResponse.expects(:new).with('xml').returns(mock(:results => 'analytics'))
15
+
16
+ assert_equal 'analytics', TestReport.results(profile)
17
+ end
18
+ end
19
+ end
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), 'test_helper')
1
+ require File.join(File.dirname(__FILE__), '..', '/test_helper')
2
2
 
3
3
  module Garb
4
4
  class SessionTest < Test::Unit::TestCase
@@ -0,0 +1,9 @@
1
+ require File.join(File.dirname(__FILE__), '..', '/test_helper')
2
+
3
+ class StringTest < Test::Unit::TestCase
4
+ context "An instance of a String" do
5
+ should 'prefix a string with ga: for GA' do
6
+ assert_equal 'ga:bob', 'bob'.to_ga
7
+ end
8
+ end
9
+ end
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/test_helper'
1
+ require File.join(File.dirname(__FILE__), '..', '/test_helper')
2
2
 
3
3
  class SymbolTest < Test::Unit::TestCase
4
4
 
metadata CHANGED
@@ -1,15 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vigetlabs-garb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tony Pitale
8
+ - Justin Marney
9
+ - Patrick Reagan
8
10
  autorequire:
9
11
  bindir: bin
10
12
  cert_chain: []
11
13
 
12
- date: 2009-04-22 00:00:00 -07:00
14
+ date: 2009-04-29 00:00:00 -07:00
13
15
  default_executable:
14
16
  dependencies:
15
17
  - !ruby/object:Gem::Dependency
@@ -32,7 +34,7 @@ dependencies:
32
34
  - !ruby/object:Gem::Version
33
35
  version: 0.9.8
34
36
  version:
35
- description: A ruby gem to aid in the use of the Google Analytics API
37
+ description:
36
38
  email: tony.pitale@viget.com
37
39
  executables: []
38
40
 
@@ -41,22 +43,43 @@ extensions: []
41
43
  extra_rdoc_files: []
42
44
 
43
45
  files:
44
- - History.txt
45
46
  - README.md
46
47
  - Rakefile
47
- - garb.gemspec
48
- - lib/garb.rb
48
+ - lib/extensions
49
+ - lib/extensions/happymapper.rb
50
+ - lib/extensions/operator.rb
51
+ - lib/extensions/string.rb
52
+ - lib/extensions/symbol.rb
53
+ - lib/garb
49
54
  - lib/garb/authentication_request.rb
50
55
  - lib/garb/data_request.rb
56
+ - lib/garb/oauth_session.rb
51
57
  - lib/garb/profile.rb
52
58
  - lib/garb/report.rb
53
59
  - lib/garb/report_parameter.rb
54
60
  - lib/garb/report_response.rb
61
+ - lib/garb/resource.rb
55
62
  - lib/garb/session.rb
56
- - lib/extensions/symbol.rb
57
- - lib/extensions/string.rb
58
- - lib/extensions/operator.rb
59
- - lib/extensions/happymapper.rb
63
+ - lib/garb/version.rb
64
+ - lib/garb.rb
65
+ - test/fixtures
66
+ - test/fixtures/profile_feed.xml
67
+ - test/fixtures/report_feed.xml
68
+ - test/test_helper.rb
69
+ - test/unit
70
+ - test/unit/authentication_request_test.rb
71
+ - test/unit/data_request_test.rb
72
+ - test/unit/garb_test.rb
73
+ - test/unit/oauth_session_test.rb
74
+ - test/unit/operator_test.rb
75
+ - test/unit/profile_test.rb
76
+ - test/unit/report_parameter_test.rb
77
+ - test/unit/report_response_test.rb
78
+ - test/unit/report_test.rb
79
+ - test/unit/resource_test.rb
80
+ - test/unit/session_test.rb
81
+ - test/unit/string_test.rb
82
+ - test/unit/symbol_test.rb
60
83
  has_rdoc: false
61
84
  homepage: http://github.com/vigetlabs/garb
62
85
  post_install_message:
@@ -84,16 +107,21 @@ signing_key:
84
107
  specification_version: 2
85
108
  summary: Google Analytics API Ruby Wrapper
86
109
  test_files:
87
- - test/authentication_request_test.rb
88
- - test/data_request_test.rb
89
- - test/garb_test.rb
90
- - test/operator_test.rb
91
- - test/profile_test.rb
92
- - test/report_parameter_test.rb
93
- - test/report_response_test.rb
94
- - test/report_test.rb
95
- - test/session_test.rb
96
- - test/symbol_test.rb
97
- - test/test_helper.rb
110
+ - test/fixtures
98
111
  - test/fixtures/profile_feed.xml
99
112
  - test/fixtures/report_feed.xml
113
+ - test/test_helper.rb
114
+ - test/unit
115
+ - test/unit/authentication_request_test.rb
116
+ - test/unit/data_request_test.rb
117
+ - test/unit/garb_test.rb
118
+ - test/unit/oauth_session_test.rb
119
+ - test/unit/operator_test.rb
120
+ - test/unit/profile_test.rb
121
+ - test/unit/report_parameter_test.rb
122
+ - test/unit/report_response_test.rb
123
+ - test/unit/report_test.rb
124
+ - test/unit/resource_test.rb
125
+ - test/unit/session_test.rb
126
+ - test/unit/string_test.rb
127
+ - test/unit/symbol_test.rb
data/History.txt DELETED
File without changes
data/garb.gemspec DELETED
@@ -1,42 +0,0 @@
1
- Gem::Specification.new do |s|
2
- s.name = "garb"
3
- s.version = "0.1.2"
4
- s.date = "2009-04-22"
5
- s.summary = "Google Analytics API Ruby Wrapper"
6
- s.email = "tony.pitale@viget.com"
7
- s.homepage = "http://github.com/vigetlabs/garb"
8
- s.description = "A ruby gem to aid in the use of the Google Analytics API"
9
- s.has_rdoc = false
10
- s.authors = ["Tony Pitale"]
11
- s.files = ["History.txt",
12
- "README.md",
13
- "Rakefile",
14
- "garb.gemspec",
15
- "lib/garb.rb",
16
- "lib/garb/authentication_request.rb",
17
- "lib/garb/data_request.rb",
18
- "lib/garb/profile.rb",
19
- "lib/garb/report.rb",
20
- "lib/garb/report_parameter.rb",
21
- "lib/garb/report_response.rb",
22
- "lib/garb/session.rb",
23
- "lib/extensions/symbol.rb",
24
- "lib/extensions/string.rb",
25
- "lib/extensions/operator.rb",
26
- "lib/extensions/happymapper.rb"]
27
- s.test_files = ['test/authentication_request_test.rb',
28
- 'test/data_request_test.rb',
29
- 'test/garb_test.rb',
30
- 'test/operator_test.rb',
31
- 'test/profile_test.rb',
32
- 'test/report_parameter_test.rb',
33
- 'test/report_response_test.rb',
34
- 'test/report_test.rb',
35
- 'test/session_test.rb',
36
- 'test/symbol_test.rb',
37
- 'test/test_helper.rb',
38
- 'test/fixtures/profile_feed.xml',
39
- 'test/fixtures/report_feed.xml']
40
- s.add_dependency("jnunemaker-happymapper", [">= 0.2.2"])
41
- s.add_dependency("libxml-ruby", [">= 0.9.8"])
42
- end
data/test/report_test.rb DELETED
@@ -1,124 +0,0 @@
1
- require File.join(File.dirname(__FILE__), 'test_helper')
2
-
3
- module Garb
4
- class ReportTest < Test::Unit::TestCase
5
-
6
- context "An instance of the Report class" do
7
- setup do
8
- @now = Time.now
9
- Time.stubs(:now).returns(@now)
10
- @profile = stub(:table_id => 'ga:1234')
11
- @report = Report.new(@profile)
12
- end
13
-
14
- %w(metrics dimensions sort filters).each do |param|
15
- should "have parameters for #{param}" do
16
- assert @report.send(:"#{param}").is_a?(ReportParameter)
17
- end
18
- end
19
-
20
- should "have a start_date" do
21
- report = Report.new(@profile, :start_date => @now)
22
- assert_equal @now, report.start_date
23
- end
24
-
25
- should "have a default start_date of one month ago" do
26
- month_ago = @now - Report::MONTH
27
- assert_equal month_ago, @report.start_date
28
- end
29
-
30
- should "have an end_date" do
31
- report = Report.new(@profile, :end_date => @now)
32
- assert_equal @now, report.end_date
33
- end
34
-
35
- should "have a default end_date of now" do
36
- assert_equal @now, @report.end_date
37
- end
38
-
39
- should "have max results if set" do
40
- @report.max_results = 5
41
- assert_equal({'max-results' => 5}, @report.page_params)
42
- end
43
-
44
- should "have an empty hash if max results not set" do
45
- assert_equal({}, @report.page_params)
46
- end
47
-
48
- should "have a profile" do
49
- assert_equal @profile, @report.profile
50
- end
51
-
52
- should "return default params with no options" do
53
- Report.expects(:format_time).with(@report.start_date).returns('start')
54
- Report.expects(:format_time).with(@report.end_date).returns('end')
55
-
56
- params = {'ids' => 'ga:1234', 'start-date' => 'start', 'end-date' => 'end'}
57
- assert_equal params, @report.default_params
58
- end
59
-
60
- should "combine parameters for request" do
61
- @report.sort.expects(:to_params).returns({'sort' => 'value'})
62
- @report.filters.expects(:to_params).returns({'filters' => 'value'})
63
- @report.metrics.expects(:to_params).returns({'metrics' => 'value'})
64
- @report.dimensions.expects(:to_params).returns({'dimensions' => 'value'})
65
-
66
- @report.expects(:page_params).returns({})
67
- @report.expects(:default_params).returns({'ids' => 'ga:1234'})
68
-
69
- params = {'ids' => 'ga:1234', 'metrics' => 'value', 'dimensions' => 'value', 'sort' => 'value', 'filters' => 'value'}
70
-
71
- assert_equal params, @report.params
72
- end
73
-
74
- should "send a request and get the response body" do
75
- response = stub(:body => 'feed')
76
- data_request = mock
77
- data_request.expects(:send_request).with().returns(response)
78
-
79
- @report.stubs(:params).returns({'key' => 'value'})
80
- DataRequest.expects(:new).with(Report::URL, {'key' => 'value'}).returns(data_request)
81
-
82
- assert_equal 'feed', @report.send_request_for_body
83
- end
84
-
85
- should "fetch and parse all entries" do
86
- @report.expects(:send_request_for_body).with().returns('xml')
87
- ReportResponse.expects(:new).with('xml').returns(mock(:parse => ['entry']))
88
- assert_equal ['entry'], @report.all
89
- end
90
- end
91
-
92
- context "The Report class" do
93
-
94
- # should "get the value for a given entry and property" do
95
- # # entry = mock do |m|
96
- # # m.expects(:/).with().returns(['balding'])
97
- # # end
98
- # # assert_equal 'balding', Report.property_value(entry, Report.element_id(:balding))
99
- # end
100
- #
101
- # should "get the values for a given entry and array of properties" do
102
- # entry = stub
103
- # Report.stubs(:property_value).with(entry, "balding").returns('balding')
104
- # Report.stubs(:property_value).with(entry, "spaulding").returns('spaulding')
105
- #
106
- # data = Report.property_values(entry, [:balding, :spaulding])
107
- # assert_equal 'balding', data.balding
108
- # assert_equal 'spaulding', data.spaulding
109
- # end
110
- #
111
- # should "return an ostruct for an entry" do
112
- # entry = stub
113
- # Report.stubs(:property_value).with(entry, "balding").returns('balding')
114
- # assert_equal true, Report.property_values(entry, [:balding]).is_a?(OpenStruct)
115
- # end
116
-
117
- should "format time" do
118
- t = Time.now
119
- assert_equal t.strftime('%Y-%m-%d'), Report.format_time(t)
120
- end
121
- end
122
-
123
- end
124
- end