gattica 0.4.1 → 0.4.3
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/History.txt +10 -0
- data/LICENSE +1 -1
- data/VERSION.yml +1 -1
- data/gattica.gemspec +1 -1
- data/lib/gattica.rb +88 -68
- data/lib/gattica/user.rb +9 -9
- data/test/test_gattica.rb +5 -5
- metadata +19 -8
data/History.txt
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
== 0.4.3
|
|
2
|
+
* er1c fixed start-index
|
|
3
|
+
* rpanachi fixed max_results
|
|
4
|
+
|
|
5
|
+
== 0.4.2
|
|
6
|
+
* rpanachi Updates for max_results
|
|
7
|
+
* Fixed various nil references from multiple people
|
|
8
|
+
* howcast Updated Email Regex to allow "username+suffix@gmail.com"
|
|
9
|
+
* scottpersinger Added V2 API Parameter for Segment filter
|
|
10
|
+
|
|
1
11
|
== 0.4.0
|
|
2
12
|
* er1c added start_index and max_results
|
|
3
13
|
* er1c added paging for all results
|
data/LICENSE
CHANGED
data/VERSION.yml
CHANGED
data/gattica.gemspec
CHANGED
data/lib/gattica.rb
CHANGED
|
@@ -25,22 +25,22 @@ require 'gattica/data_point'
|
|
|
25
25
|
# Please see the README for usage docs.
|
|
26
26
|
|
|
27
27
|
module Gattica
|
|
28
|
-
|
|
29
|
-
VERSION = '0.4.
|
|
30
|
-
|
|
28
|
+
|
|
29
|
+
VERSION = '0.4.3'
|
|
30
|
+
|
|
31
31
|
# Creates a new instance of Gattica::Engine and gets us going. Please see the README for usage docs.
|
|
32
32
|
#
|
|
33
33
|
# ga = Gattica.new({:email => 'anonymous@anon.com', :password => 'password, :profile_id => 123456 })
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
def self.new(*args)
|
|
36
36
|
Engine.new(*args)
|
|
37
37
|
end
|
|
38
|
-
|
|
39
|
-
# The real meat of Gattica, deals with talking to GA, returning and parsing results. You actually get
|
|
38
|
+
|
|
39
|
+
# The real meat of Gattica, deals with talking to GA, returning and parsing results. You actually get
|
|
40
40
|
# an instance of this when you go Gattica.new()
|
|
41
|
-
|
|
41
|
+
|
|
42
42
|
class Engine
|
|
43
|
-
|
|
43
|
+
|
|
44
44
|
SERVER = 'www.google.com'
|
|
45
45
|
PORT = 443
|
|
46
46
|
SECURE = true
|
|
@@ -48,10 +48,10 @@ module Gattica
|
|
|
48
48
|
DEFAULT_OPTIONS = { :email => nil, :password => nil, :token => nil, :profile_id => nil, :debug => false, :headers => {}, :logger => Logger.new(STDOUT) }
|
|
49
49
|
FILTER_METRIC_OPERATORS = %w{ == != > < >= <= }
|
|
50
50
|
FILTER_DIMENSION_OPERATORS = %w{ == != =~ !~ =@ ~@ }
|
|
51
|
-
|
|
51
|
+
|
|
52
52
|
attr_reader :user
|
|
53
53
|
attr_accessor :profile_id, :token
|
|
54
|
-
|
|
54
|
+
|
|
55
55
|
# Create a user, and get them authorized.
|
|
56
56
|
# If you're making a web app you're going to want to save the token that's retrieved by Gattica
|
|
57
57
|
# so that you can use it later (Google recommends not re-authenticating the user for each and every request)
|
|
@@ -62,15 +62,17 @@ module Gattica
|
|
|
62
62
|
# Or if you already have the token (because you authenticated previously and now want to reuse that session):
|
|
63
63
|
#
|
|
64
64
|
# ga = Gattica.new({:token => '23ohda09hw...', :profile_id => 123456})
|
|
65
|
-
|
|
65
|
+
|
|
66
66
|
def initialize(options={})
|
|
67
67
|
@options = DEFAULT_OPTIONS.merge(options)
|
|
68
68
|
@logger = @options[:logger]
|
|
69
|
-
|
|
69
|
+
@logger.level = Logger::INFO
|
|
70
|
+
|
|
71
|
+
|
|
70
72
|
@profile_id = @options[:profile_id] # if you don't include the profile_id now, you'll have to set it manually later via Gattica::Engine#profile_id=
|
|
71
73
|
@user_accounts = nil # filled in later if the user ever calls Gattica::Engine#accounts
|
|
72
74
|
@headers = {}.merge(@options[:headers]) # headers used for any HTTP requests (Google requires a special 'Authorization' header which is set any time @token is set)
|
|
73
|
-
|
|
75
|
+
|
|
74
76
|
# save a proxy-aware http connection for everyone to use
|
|
75
77
|
proxy_host = nil
|
|
76
78
|
proxy_port = nil
|
|
@@ -85,7 +87,7 @@ module Gattica
|
|
|
85
87
|
@http = Net::HTTP::Proxy(proxy_host,proxy_port).new(SERVER, PORT)
|
|
86
88
|
@http.use_ssl = SECURE
|
|
87
89
|
@http.set_debug_output $stdout if @options[:debug]
|
|
88
|
-
|
|
90
|
+
|
|
89
91
|
# authenticate
|
|
90
92
|
if @options[:email] && @options[:password] # email and password: authenticate, get a token from Google's ClientLogin, save it for later
|
|
91
93
|
@user = User.new(@options[:email], @options[:password])
|
|
@@ -96,11 +98,11 @@ module Gattica
|
|
|
96
98
|
else # no login or token, you can't do anything
|
|
97
99
|
raise GatticaError::NoLoginOrToken, 'You must provide an email and password, or authentication token'
|
|
98
100
|
end
|
|
99
|
-
|
|
101
|
+
|
|
100
102
|
# TODO: check that the user has access to the specified profile and show an error here rather than wait for Google to respond with a message
|
|
101
103
|
end
|
|
102
|
-
|
|
103
|
-
|
|
104
|
+
|
|
105
|
+
|
|
104
106
|
# Returns the list of accounts the user has access to. A user may have multiple accounts on Google Analytics
|
|
105
107
|
# and each account may have multiple profiles. You need the profile_id in order to get info from GA. If you
|
|
106
108
|
# don't know the profile_id then use this method to get a list of all them. Then set the profile_id of your
|
|
@@ -116,7 +118,7 @@ module Gattica
|
|
|
116
118
|
# get the accounts and find a profile_id - you apparently already know it!
|
|
117
119
|
#
|
|
118
120
|
# See Gattica::Engine#get to see how to get some data.
|
|
119
|
-
|
|
121
|
+
|
|
120
122
|
def accounts
|
|
121
123
|
# if we haven't retrieved the user's accounts yet, get them now and save them
|
|
122
124
|
if @user_accounts.nil?
|
|
@@ -133,35 +135,35 @@ module Gattica
|
|
|
133
135
|
#
|
|
134
136
|
# gs = Gattica.new({:email => 'johndoe@google.com', :password => 'password', :profile_id => 123456})
|
|
135
137
|
# fh = File.new("file.csv", "w")
|
|
136
|
-
# gs.get_to_csv({ :start_date => '2008-01-01',
|
|
137
|
-
# :end_date => '2008-02-01',
|
|
138
|
-
# :dimensions => 'browser',
|
|
139
|
-
# :metrics => 'pageviews',
|
|
138
|
+
# gs.get_to_csv({ :start_date => '2008-01-01',
|
|
139
|
+
# :end_date => '2008-02-01',
|
|
140
|
+
# :dimensions => 'browser',
|
|
141
|
+
# :metrics => 'pageviews',
|
|
140
142
|
# :sort => 'pageviews',
|
|
141
143
|
# :filters => ['browser == Firefox']}, fh, :short)
|
|
142
144
|
#
|
|
143
145
|
# See Gattica::Engine#get to see details of arguments
|
|
144
146
|
|
|
145
|
-
def get_to_csv(args={}, fh = nil, format = :long)
|
|
147
|
+
def get_to_csv(args={}, fh = nil, format = :long)
|
|
146
148
|
raise GatticaError::InvalidFileType, "Invalid file handle" unless !fh.nil?
|
|
147
149
|
results(args, fh, :csv, format)
|
|
148
150
|
end
|
|
149
|
-
|
|
151
|
+
|
|
150
152
|
# This is the method that performs the actual request to get data.
|
|
151
153
|
#
|
|
152
154
|
# == Usage
|
|
153
155
|
#
|
|
154
156
|
# gs = Gattica.new({:email => 'johndoe@google.com', :password => 'password', :profile_id => 123456})
|
|
155
|
-
# gs.get({ :start_date => '2008-01-01',
|
|
156
|
-
# :end_date => '2008-02-01',
|
|
157
|
-
# :dimensions => 'browser',
|
|
158
|
-
# :metrics => 'pageviews',
|
|
157
|
+
# gs.get({ :start_date => '2008-01-01',
|
|
158
|
+
# :end_date => '2008-02-01',
|
|
159
|
+
# :dimensions => 'browser',
|
|
160
|
+
# :metrics => 'pageviews',
|
|
159
161
|
# :sort => 'pageviews',
|
|
160
162
|
# :filters => ['browser == Firefox']})
|
|
161
163
|
#
|
|
162
164
|
# == Input
|
|
163
165
|
#
|
|
164
|
-
# When calling +get+ you'll pass in a hash of options. For a description of what these mean to
|
|
166
|
+
# When calling +get+ you'll pass in a hash of options. For a description of what these mean to
|
|
165
167
|
# Google Analytics, see http://code.google.com/apis/analytics/docs
|
|
166
168
|
#
|
|
167
169
|
# Required values are:
|
|
@@ -184,13 +186,13 @@ module Gattica
|
|
|
184
186
|
# If a user doesn't have access to the +profile_id+ you specified, you'll receive an error.
|
|
185
187
|
# Likewise, if you attempt to access a dimension or metric that doesn't exist, you'll get an
|
|
186
188
|
# error back from Google Analytics telling you so.
|
|
187
|
-
|
|
189
|
+
|
|
188
190
|
def get(args={})
|
|
189
191
|
return results(args)
|
|
190
192
|
end
|
|
191
|
-
|
|
193
|
+
|
|
192
194
|
private
|
|
193
|
-
|
|
195
|
+
|
|
194
196
|
def results(args={}, fh=nil, type=nil, format=nil)
|
|
195
197
|
raise GatticaError::InvalidFileType, "Invalid file type" unless type.nil? ||[:csv,:xml].include?(type)
|
|
196
198
|
args = validate_and_clean(DEFAULT_ARGS.merge(args))
|
|
@@ -200,47 +202,48 @@ module Gattica
|
|
|
200
202
|
total_results = args[:max_results]
|
|
201
203
|
while(args[:start_index] < total_results)
|
|
202
204
|
query_string = build_query_string(args,@profile_id)
|
|
203
|
-
@logger.
|
|
205
|
+
@logger.info("Start Index: #{args[:start_index]}, Total Results: #{total_results}, Query String: " + query_string) if @options[:debug]
|
|
204
206
|
|
|
205
207
|
data = do_http_get("/analytics/feeds/data?#{query_string}")
|
|
206
208
|
result = DataSet.new(Hpricot.XML(data))
|
|
207
|
-
|
|
209
|
+
|
|
208
210
|
#handle returning results
|
|
209
211
|
results.points.concat(result.points) if !results.nil? && fh.nil?
|
|
212
|
+
results = result if results.nil?
|
|
213
|
+
|
|
210
214
|
#handle csv
|
|
211
|
-
|
|
212
215
|
if(!fh.nil? && type == :csv && header == 0)
|
|
213
216
|
fh.write result.to_csv_header(format)
|
|
214
|
-
header = 1
|
|
217
|
+
header = 1
|
|
215
218
|
end
|
|
216
|
-
|
|
219
|
+
|
|
217
220
|
fh.write result.to_csv(:noheader) if !fh.nil? && type == :csv
|
|
218
221
|
fh.flush if !fh.nil?
|
|
219
|
-
|
|
220
|
-
|
|
222
|
+
|
|
223
|
+
# Update Loop Counters
|
|
221
224
|
total_results = result.total_results
|
|
222
225
|
args[:start_index] += args[:max_results]
|
|
223
226
|
break if !args[:page] # only continue while if we are suppose to page
|
|
224
|
-
end
|
|
227
|
+
end
|
|
225
228
|
return results if fh.nil?
|
|
226
229
|
end
|
|
227
|
-
|
|
230
|
+
|
|
228
231
|
# Since google wants the token to appear in any HTTP call's header, we have to set that header
|
|
229
232
|
# again any time @token is changed so we override the default writer (note that you need to set
|
|
230
233
|
# @token with self.token= instead of @token=)
|
|
231
|
-
|
|
234
|
+
|
|
232
235
|
def token=(token)
|
|
233
236
|
@token = token
|
|
234
237
|
set_http_headers
|
|
235
238
|
end
|
|
236
|
-
|
|
237
|
-
|
|
239
|
+
|
|
240
|
+
|
|
238
241
|
# Does the work of making HTTP calls and then going through a suite of tests on the response to make
|
|
239
242
|
# sure it's valid and not an error
|
|
240
|
-
|
|
243
|
+
|
|
241
244
|
def do_http_get(query_string)
|
|
242
245
|
response, data = @http.get(query_string, @headers)
|
|
243
|
-
|
|
246
|
+
|
|
244
247
|
# error checking
|
|
245
248
|
if response.code != '200'
|
|
246
249
|
case response.code
|
|
@@ -252,29 +255,38 @@ module Gattica
|
|
|
252
255
|
raise GatticaError::UnknownAnalyticsError, response.body + " (status code: #{response.code})"
|
|
253
256
|
end
|
|
254
257
|
end
|
|
255
|
-
|
|
258
|
+
|
|
256
259
|
return data
|
|
257
260
|
end
|
|
258
|
-
|
|
261
|
+
|
|
259
262
|
private
|
|
260
|
-
|
|
263
|
+
|
|
261
264
|
# Sets up the HTTP headers that Google expects (this is called any time @token is set either by Gattica
|
|
262
265
|
# or manually by the user since the header must include the token)
|
|
263
266
|
def set_http_headers
|
|
264
267
|
@headers['Authorization'] = "GoogleLogin auth=#{@token}"
|
|
268
|
+
@headers['GData-Version']= '2'
|
|
265
269
|
end
|
|
266
|
-
|
|
267
|
-
|
|
270
|
+
|
|
271
|
+
|
|
268
272
|
# Creates a valid query string for GA
|
|
269
273
|
def build_query_string(args,profile)
|
|
270
274
|
query_params = args.clone
|
|
275
|
+
|
|
276
|
+
# Internal Parameters, don't pass to google
|
|
277
|
+
query_params.delete(:debug)
|
|
278
|
+
query_params.delete(:page)
|
|
279
|
+
|
|
271
280
|
ga_start_date = query_params.delete(:start_date)
|
|
272
281
|
ga_end_date = query_params.delete(:end_date)
|
|
273
282
|
ga_dimensions = query_params.delete(:dimensions)
|
|
274
283
|
ga_metrics = query_params.delete(:metrics)
|
|
275
284
|
ga_sort = query_params.delete(:sort)
|
|
276
285
|
ga_filters = query_params.delete(:filters)
|
|
277
|
-
|
|
286
|
+
ga_segment = query_params.delete(:segment)
|
|
287
|
+
ga_start_index = query_params.delete(:start_index) || query_params.delete(:'start-index')
|
|
288
|
+
ga_max_results = query_params.delete(:max_results) || query_params.delete(:'max-results')
|
|
289
|
+
|
|
278
290
|
output = "ids=ga:#{profile}&start-date=#{ga_start_date}&end-date=#{ga_end_date}"
|
|
279
291
|
unless ga_dimensions.nil? || ga_dimensions.empty?
|
|
280
292
|
output += '&dimensions=' + ga_dimensions.collect do |dimension|
|
|
@@ -291,9 +303,13 @@ module Gattica
|
|
|
291
303
|
sort[0..0] == '-' ? "-ga:#{sort[1..-1]}" : "ga:#{sort}" # if the first character is a dash, move it before the ga:
|
|
292
304
|
end.join(',')
|
|
293
305
|
end
|
|
294
|
-
|
|
306
|
+
|
|
307
|
+
unless ga_segment.nil? || ga_segment.empty?
|
|
308
|
+
output += "&segment=#{ga_segment}"
|
|
309
|
+
end
|
|
310
|
+
|
|
295
311
|
# TODO: update so that in regular expression filters (=~ and !~), any initial special characters in the regular expression aren't also picked up as part of the operator (doesn't cause a problem, but just feels dirty)
|
|
296
|
-
unless args[:filters].empty? # filters are a little more complicated because they can have all kinds of modifiers
|
|
312
|
+
unless args[:filters].nil? || args[:filters].empty? # filters are a little more complicated because they can have all kinds of modifiers
|
|
297
313
|
output += '&filters=' + args[:filters].collect do |filter|
|
|
298
314
|
match, name, operator, expression = *filter.match(/^(\w*)\s*([=!<>~@]*)\s*(.*)$/) # splat the resulting Match object to pull out the parts automatically
|
|
299
315
|
unless name.empty? || operator.empty? || expression.empty? # make sure they all contain something
|
|
@@ -303,23 +319,27 @@ module Gattica
|
|
|
303
319
|
end
|
|
304
320
|
end.join(';')
|
|
305
321
|
end
|
|
306
|
-
|
|
322
|
+
|
|
323
|
+
output += "&start-index=#{ga_start_index}" unless ga_start_index.nil? || ga_start_index.to_s.empty?
|
|
324
|
+
output += "&max-results=#{ga_max_results}" unless ga_max_results.nil? || ga_max_results.to_s.empty?
|
|
325
|
+
|
|
307
326
|
query_params.inject(output) {|m,(key,value)| m << "&#{key}=#{value}"}
|
|
308
|
-
|
|
327
|
+
|
|
309
328
|
return output
|
|
310
329
|
end
|
|
311
|
-
|
|
312
|
-
|
|
330
|
+
|
|
331
|
+
|
|
313
332
|
# Validates that the args passed to +get+ are valid
|
|
314
333
|
def validate_and_clean(args)
|
|
315
|
-
|
|
316
|
-
raise GatticaError::
|
|
317
|
-
raise GatticaError::MissingEndDate, ':end_date is required' if args[:end_date].nil? || args[:end_date].empty?
|
|
334
|
+
raise GatticaError::MissingStartDate, ':start_date is required' if args[:start_date].nil? || args[:start_date].to_s.empty?
|
|
335
|
+
raise GatticaError::MissingEndDate, ':end_date is required' if args[:end_date].nil? || args[:end_date].to_s.empty?
|
|
318
336
|
raise GatticaError::TooManyDimensions, 'You can only have a maximum of 7 dimensions' if args[:dimensions] && (args[:dimensions].is_a?(Array) && args[:dimensions].length > 7)
|
|
319
337
|
raise GatticaError::TooManyMetrics, 'You can only have a maximum of 10 metrics' if args[:metrics] && (args[:metrics].is_a?(Array) && args[:metrics].length > 10)
|
|
320
|
-
|
|
321
|
-
possible =
|
|
322
|
-
|
|
338
|
+
|
|
339
|
+
possible = []
|
|
340
|
+
possible << args[:dimensions] << args[:metrics]
|
|
341
|
+
possible.flatten!
|
|
342
|
+
|
|
323
343
|
# make sure that the user is only trying to sort fields that they've previously included with dimensions and metrics
|
|
324
344
|
if args[:sort]
|
|
325
345
|
missing = args[:sort].find_all do |arg|
|
|
@@ -329,7 +349,7 @@ module Gattica
|
|
|
329
349
|
raise GatticaError::InvalidSort, "You are trying to sort by fields that are not in the available dimensions or metrics: #{missing.join(', ')}"
|
|
330
350
|
end
|
|
331
351
|
end
|
|
332
|
-
|
|
352
|
+
|
|
333
353
|
# make sure that the user is only trying to filter fields that are in dimensions or metrics
|
|
334
354
|
if args[:filters]
|
|
335
355
|
missing = args[:filters].find_all do |arg|
|
|
@@ -339,10 +359,10 @@ module Gattica
|
|
|
339
359
|
raise GatticaError::InvalidSort, "You are trying to filter by fields that are not in the available dimensions or metrics: #{missing.join(', ')}"
|
|
340
360
|
end
|
|
341
361
|
end
|
|
342
|
-
|
|
362
|
+
|
|
343
363
|
return args
|
|
344
364
|
end
|
|
345
|
-
|
|
346
|
-
|
|
365
|
+
|
|
366
|
+
|
|
347
367
|
end
|
|
348
368
|
end
|
data/lib/gattica/user.rb
CHANGED
|
@@ -1,31 +1,31 @@
|
|
|
1
1
|
module Gattica
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
# Represents a user to be authenticated by GA
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
class User
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
include Convertible
|
|
8
|
-
|
|
8
|
+
|
|
9
9
|
attr_accessor :email, :password
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
def initialize(email,password)
|
|
12
12
|
@email = email
|
|
13
13
|
@password = password
|
|
14
14
|
validate
|
|
15
15
|
end
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
# User gets a special +to_h+ because Google expects +Email+ and +Passwd+ instead of our nicer internal names
|
|
18
18
|
def to_h
|
|
19
19
|
{ :Email => @email,
|
|
20
20
|
:Passwd => @password }
|
|
21
21
|
end
|
|
22
|
-
|
|
22
|
+
|
|
23
23
|
private
|
|
24
24
|
# Determine whether or not this is a valid user
|
|
25
25
|
def validate
|
|
26
|
-
raise GatticaError::InvalidEmail, "The email address '#{@email}' is not valid" if not @email.match(/^(?:[_a-z0-9-]+)(\.[_a-z0-9-]+)*@([a-z0-9-]+)(\.[a-zA-Z0-9\-\.]+)*(\.[a-z]{2,4})$/i)
|
|
26
|
+
raise GatticaError::InvalidEmail, "The email address '#{@email}' is not valid" if not @email.match(/^(?:[\+_a-z0-9-]+)(\.[_a-z0-9-]+)*@([a-z0-9-]+)(\.[a-zA-Z0-9\-\.]+)*(\.[a-z]{2,4})$/i)
|
|
27
27
|
raise GatticaError::InvalidPassword, "The password cannot be blank" if @password.empty? || @password.nil?
|
|
28
28
|
end
|
|
29
|
-
|
|
29
|
+
|
|
30
30
|
end
|
|
31
31
|
end
|
data/test/test_gattica.rb
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
require File.dirname(__FILE__) + '/helper'
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
class TestUser < Test::Unit::TestCase
|
|
4
4
|
def test_build_query_string
|
|
5
5
|
@gattica = Gattica.new(:token => 'ga-token', :profile_id => 'ga-profile_id')
|
|
6
6
|
expected = "ids=ga:ga-profile_id&start-date=2008-01-02&end-date=2008-01-03&dimensions=ga:pageTitle,ga:pagePath&metrics=ga:pageviews&sort=-ga:pageviews&max-results=3"
|
|
7
7
|
result = @gattica.send(:build_query_string, {
|
|
8
|
-
:start_date => Date.civil(2008,1,2),
|
|
8
|
+
:start_date => Date.civil(2008,1,2),
|
|
9
9
|
:end_date => Date.civil(2008,1,3),
|
|
10
|
-
:dimensions => ['pageTitle','pagePath'],
|
|
11
|
-
:metrics => ['pageviews'],
|
|
10
|
+
:dimensions => ['pageTitle','pagePath'],
|
|
11
|
+
:metrics => ['pageviews'],
|
|
12
12
|
:sort => '-pageviews',
|
|
13
|
-
|
|
13
|
+
:max_results => '3'}, 'ga-profile_id')
|
|
14
14
|
assert_equal expected, result
|
|
15
15
|
end
|
|
16
16
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: gattica
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
|
|
4
|
+
prerelease: false
|
|
5
|
+
segments:
|
|
6
|
+
- 0
|
|
7
|
+
- 4
|
|
8
|
+
- 3
|
|
9
|
+
version: 0.4.3
|
|
5
10
|
platform: ruby
|
|
6
11
|
authors:
|
|
7
12
|
- The Active Network
|
|
@@ -14,14 +19,18 @@ default_executable:
|
|
|
14
19
|
dependencies:
|
|
15
20
|
- !ruby/object:Gem::Dependency
|
|
16
21
|
name: hpricot
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
prerelease: false
|
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
|
20
24
|
requirements:
|
|
21
25
|
- - ">="
|
|
22
26
|
- !ruby/object:Gem::Version
|
|
27
|
+
segments:
|
|
28
|
+
- 0
|
|
29
|
+
- 6
|
|
30
|
+
- 164
|
|
23
31
|
version: 0.6.164
|
|
24
|
-
|
|
32
|
+
type: :runtime
|
|
33
|
+
version_requirements: *id001
|
|
25
34
|
description: Gattica is a Ruby library for extracting data from the Google Analytics API.
|
|
26
35
|
email: rob.cameron@active.com
|
|
27
36
|
executables: []
|
|
@@ -68,18 +77,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
68
77
|
requirements:
|
|
69
78
|
- - ">="
|
|
70
79
|
- !ruby/object:Gem::Version
|
|
80
|
+
segments:
|
|
81
|
+
- 0
|
|
71
82
|
version: "0"
|
|
72
|
-
version:
|
|
73
83
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
74
84
|
requirements:
|
|
75
85
|
- - ">="
|
|
76
86
|
- !ruby/object:Gem::Version
|
|
87
|
+
segments:
|
|
88
|
+
- 0
|
|
77
89
|
version: "0"
|
|
78
|
-
version:
|
|
79
90
|
requirements: []
|
|
80
91
|
|
|
81
92
|
rubyforge_project:
|
|
82
|
-
rubygems_version: 1.3.
|
|
93
|
+
rubygems_version: 1.3.6
|
|
83
94
|
signing_key:
|
|
84
95
|
specification_version: 3
|
|
85
96
|
summary: Gattica is a Ruby library for extracting data from the Google Analytics API.
|