legato 0.5.1 → 0.5.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/.travis.yml +1 -0
- data/CHANGELOG.md +9 -0
- data/CODE_OF_CONDUCT.md +22 -0
- data/README.md +12 -0
- data/lib/legato.rb +3 -0
- data/lib/legato/management/account.rb +16 -2
- data/lib/legato/management/account_summary.rb +32 -0
- data/lib/legato/management/finder.rb +4 -17
- data/lib/legato/management/profile.rb +8 -0
- data/lib/legato/management/query.rb +25 -0
- data/lib/legato/management/web_property.rb +15 -1
- data/lib/legato/model.rb +1 -0
- data/lib/legato/query.rb +27 -8
- data/lib/legato/request.rb +46 -0
- data/lib/legato/response.rb +8 -4
- data/lib/legato/user.rb +10 -30
- data/lib/legato/version.rb +1 -1
- data/spec/lib/legato/management/account_summary_spec.rb +170 -0
- data/spec/lib/legato/query_spec.rb +42 -0
- data/spec/lib/legato/user_spec.rb +35 -36
- data/spec/support/examples/management_finder.rb +10 -16
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 980eb1079898deac8afc471a03804fda0cc3865a
|
4
|
+
data.tar.gz: 90eb6e06d3ccfb0ebb5cb178c8e81ef9808beef6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bdb333f5453cb364f28a431eb1b6b84cf3c8fedd1df39a05e3af0bf6784cda44e9279b2e81051d81158daa5717cc8ed7a6ce2786deed0b59e180266acb66ef0b
|
7
|
+
data.tar.gz: 6596be013de3f10f9704e9ab11167316d475919038200770f34130b99dc555218905420c7cd36a000bba44db4926b054797ba3ef497ee7bda2f3b28a3d79bb1b
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
2.2.2
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
## Legato 0.5.2 ##
|
2
|
+
|
3
|
+
* Refactor `User.request` into a `Request` class
|
4
|
+
* Implement a query class for management requests
|
5
|
+
* Use `Request` for management with new query
|
6
|
+
* Add `quota_user` and `user_ip` on `User` for quota management
|
7
|
+
|
8
|
+
*Tony Pitale*
|
9
|
+
|
1
10
|
## Legato 0.5.1 ##
|
2
11
|
|
3
12
|
* `Legato::User#segments`
|
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# Contributor Code of Conduct
|
2
|
+
|
3
|
+
As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
|
4
|
+
|
5
|
+
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality.
|
6
|
+
|
7
|
+
Examples of unacceptable behavior by participants include:
|
8
|
+
|
9
|
+
* The use of sexualized language or imagery
|
10
|
+
* Personal attacks
|
11
|
+
* Trolling or insulting/derogatory comments
|
12
|
+
* Public or private harassment
|
13
|
+
* Publishing other's private information, such as physical or electronic addresses, without explicit permission
|
14
|
+
* Other unethical or unprofessional conduct.
|
15
|
+
|
16
|
+
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team.
|
17
|
+
|
18
|
+
This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community.
|
19
|
+
|
20
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
|
21
|
+
|
22
|
+
This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0, available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/)
|
data/README.md
CHANGED
@@ -253,6 +253,7 @@ profile.exit.high_exits.low_pageviews
|
|
253
253
|
Legato::Management::Account.all(user)
|
254
254
|
Legato::Management::WebProperty.all(user)
|
255
255
|
Legato::Management::Profile.all(user)
|
256
|
+
Legato::Management::Goal.all(user)
|
256
257
|
```
|
257
258
|
## Other Parameters Can be Passed to a call to #results ##
|
258
259
|
|
@@ -286,6 +287,17 @@ query.realtime? #=> true
|
|
286
287
|
query.tracking_scope #=> 'rt'
|
287
288
|
```
|
288
289
|
|
290
|
+
## Managing Quotas ##
|
291
|
+
|
292
|
+
Assigning a `quota_user` or `user_ip` on a user instance will be used by management and query requests.
|
293
|
+
|
294
|
+
```ruby
|
295
|
+
user = Legato::User.new(access_token)
|
296
|
+
user.quota_user = 'some_unique_user_identifier'
|
297
|
+
# OR
|
298
|
+
user.user_ip = ip_address_from_a_web_user_or_something
|
299
|
+
```
|
300
|
+
|
289
301
|
## License ##
|
290
302
|
|
291
303
|
(The MIT License)
|
data/lib/legato.rb
CHANGED
@@ -41,12 +41,15 @@ module Legato
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
+
require 'legato/request'
|
44
45
|
require 'legato/user'
|
45
46
|
require 'legato/profile_methods'
|
46
47
|
|
48
|
+
require 'legato/management/query'
|
47
49
|
require 'legato/management/finder'
|
48
50
|
require 'legato/management/segment'
|
49
51
|
require 'legato/management/account'
|
52
|
+
require 'legato/management/account_summary'
|
50
53
|
require 'legato/management/web_property'
|
51
54
|
require 'legato/management/profile'
|
52
55
|
require 'legato/management/goal'
|
@@ -12,6 +12,7 @@ module Legato
|
|
12
12
|
end
|
13
13
|
|
14
14
|
attr_accessor :id, :name, :user
|
15
|
+
attr_writer :web_properties
|
15
16
|
|
16
17
|
def initialize(attributes, user)
|
17
18
|
self.user = user
|
@@ -21,16 +22,29 @@ module Legato
|
|
21
22
|
end
|
22
23
|
|
23
24
|
def web_properties
|
24
|
-
WebProperty.for_account(self)
|
25
|
+
@web_properties ||= WebProperty.for_account(self)
|
25
26
|
end
|
26
27
|
|
27
28
|
def profiles
|
28
|
-
|
29
|
+
@web_properties ?
|
30
|
+
@web_properties.map { |property| property.profiles }.flatten :
|
31
|
+
Profile.for_account(self)
|
29
32
|
end
|
30
33
|
|
31
34
|
def self.from_child(child)
|
32
35
|
all(child.user).detect {|a| a.id == child.account_id}
|
33
36
|
end
|
37
|
+
|
38
|
+
def self.build_from_summary(attributes, user)
|
39
|
+
properties = attributes['webProperties'] || attributes[:webProperties]
|
40
|
+
|
41
|
+
Account.new(attributes, user).tap { |account|
|
42
|
+
account.web_properties = properties.map { |property|
|
43
|
+
property['accountId'] = account.id
|
44
|
+
WebProperty.build_from_summary(property, user, account)
|
45
|
+
}
|
46
|
+
}
|
47
|
+
end
|
34
48
|
end
|
35
49
|
end
|
36
50
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Legato
|
2
|
+
module Management
|
3
|
+
class AccountSummary
|
4
|
+
extend Finder
|
5
|
+
|
6
|
+
def self.default_path
|
7
|
+
"/accountSummaries"
|
8
|
+
end
|
9
|
+
|
10
|
+
def path
|
11
|
+
""
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_accessor :user, :account
|
15
|
+
|
16
|
+
def initialize(attributes, user)
|
17
|
+
self.user = user
|
18
|
+
|
19
|
+
@account = Account.build_from_summary(attributes, user)
|
20
|
+
end
|
21
|
+
|
22
|
+
def web_properties
|
23
|
+
@account.web_properties
|
24
|
+
end
|
25
|
+
|
26
|
+
def profiles
|
27
|
+
@account.profiles
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -6,28 +6,15 @@ module Legato
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def all(user, path=default_path)
|
9
|
-
|
9
|
+
query = Legato::Management::Query.new(base_uri + path, self)
|
10
10
|
|
11
|
-
|
12
|
-
items = MultiJson.decode(json).fetch('items', [])
|
13
|
-
items.map {|item| new(item, user)}
|
11
|
+
user.request(query).items.map {|item| new(item, user)}
|
14
12
|
end
|
15
13
|
|
16
14
|
def get(user, path)
|
17
|
-
|
18
|
-
json = user.access_token.get(uri).body
|
15
|
+
query = Legato::Management::Query.new(base_uri + path, self)
|
19
16
|
|
20
|
-
new(
|
21
|
-
end
|
22
|
-
|
23
|
-
def uri_for_user(user, path)
|
24
|
-
if user.api_key
|
25
|
-
# oauth + api_key
|
26
|
-
base_uri + path + "?key=#{user.api_key}"
|
27
|
-
else
|
28
|
-
# oauth 2
|
29
|
-
base_uri + path
|
30
|
-
end
|
17
|
+
new(user.request(query).data, user)
|
31
18
|
end
|
32
19
|
end
|
33
20
|
end
|
@@ -22,6 +22,7 @@ module Legato
|
|
22
22
|
|
23
23
|
attr_accessor *GA_ATTRIBUTES.keys
|
24
24
|
attr_accessor :user, :attributes
|
25
|
+
attr_writer :account, :web_property
|
25
26
|
|
26
27
|
def initialize(attributes, user)
|
27
28
|
self.user = user
|
@@ -52,6 +53,13 @@ module Legato
|
|
52
53
|
def goals
|
53
54
|
Goal.for_profile(self)
|
54
55
|
end
|
56
|
+
|
57
|
+
def self.build_from_summary(attributes, user, account, web_property)
|
58
|
+
Profile.new(attributes, user).tap { |profile|
|
59
|
+
profile.account = account
|
60
|
+
profile.web_property = web_property
|
61
|
+
}
|
62
|
+
end
|
55
63
|
end
|
56
64
|
end
|
57
65
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Legato
|
2
|
+
module Management
|
3
|
+
class Query
|
4
|
+
attr_reader :instance_klass, :base_url
|
5
|
+
|
6
|
+
attr_accessor :quota_user, :user_ip
|
7
|
+
|
8
|
+
def initialize(base_url, instance_klass)
|
9
|
+
@base_url = base_url
|
10
|
+
@instance_klass = instance_klass
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_params
|
14
|
+
{
|
15
|
+
'quotaUser' => quota_user,
|
16
|
+
'userIp' => user_ip
|
17
|
+
}.reject {|_,v| v.nil?}
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_query_string
|
21
|
+
to_params.map {|k,v| [k,v].join("=")}.join("&")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -20,6 +20,7 @@ module Legato
|
|
20
20
|
|
21
21
|
attr_accessor *GA_ATTRIBUTES.keys
|
22
22
|
attr_accessor :user, :attributes
|
23
|
+
attr_writer :account, :profiles
|
23
24
|
|
24
25
|
def initialize(attributes, user)
|
25
26
|
self.user = user
|
@@ -36,7 +37,7 @@ module Legato
|
|
36
37
|
end
|
37
38
|
|
38
39
|
def profiles
|
39
|
-
Profile.for_web_property(self)
|
40
|
+
@profiles ||= Profile.for_web_property(self)
|
40
41
|
end
|
41
42
|
|
42
43
|
def account
|
@@ -48,6 +49,19 @@ module Legato
|
|
48
49
|
|
49
50
|
get(child.user, path)
|
50
51
|
end
|
52
|
+
|
53
|
+
def self.build_from_summary(attributes, user, account)
|
54
|
+
profiles = attributes.delete('profiles') || attributes.delete(:profiles)
|
55
|
+
|
56
|
+
WebProperty.new(attributes, user).tap { |web_property|
|
57
|
+
web_property.account = account
|
58
|
+
web_property.profiles = profiles.map { |profile|
|
59
|
+
profile['accountId'] = account.id
|
60
|
+
profile['webPropertyId'] = web_property.id
|
61
|
+
Profile.build_from_summary(profile, user, account, web_property)
|
62
|
+
}
|
63
|
+
}
|
64
|
+
end
|
51
65
|
end
|
52
66
|
end
|
53
67
|
end
|
data/lib/legato/model.rb
CHANGED
@@ -81,6 +81,7 @@ module Legato
|
|
81
81
|
# * offset
|
82
82
|
# * sort
|
83
83
|
# * quota_user
|
84
|
+
# * segment_id
|
84
85
|
# @return [Query] a new query with all the filters/segments defined on the
|
85
86
|
# model, allowing for chainable behavior before kicking of the request
|
86
87
|
# to Google Analytics which returns the result data
|
data/lib/legato/query.rb
CHANGED
@@ -5,6 +5,12 @@ module Legato
|
|
5
5
|
MONTH = 2592000
|
6
6
|
REQUEST_FIELDS = 'columnHeaders/name,rows,totalResults,totalsForAllResults'
|
7
7
|
|
8
|
+
VALID_TRACKING_SCOPES = {
|
9
|
+
'ga' => 'ga',
|
10
|
+
'mcf' => 'mcf',
|
11
|
+
'rt' => 'realtime'
|
12
|
+
}
|
13
|
+
|
8
14
|
def define_filter(name, &block)
|
9
15
|
(class << self; self; end).instance_eval do
|
10
16
|
define_method(name) {|*args| apply_filter(*args, &block)}
|
@@ -29,7 +35,7 @@ module Legato
|
|
29
35
|
|
30
36
|
attr_reader :parent_klass
|
31
37
|
attr_accessor :profile, :start_date, :end_date
|
32
|
-
attr_accessor :sort, :limit, :offset, :quota_user, :sampling_level #, :segment # individual, overwritten
|
38
|
+
attr_accessor :sort, :limit, :offset, :quota_user, :user_ip, :sampling_level, :segment_id #, :segment # individual, overwritten
|
33
39
|
attr_accessor :filters, :segment_filters # combined, can be appended to
|
34
40
|
attr_accessor :tracking_scope
|
35
41
|
|
@@ -91,7 +97,7 @@ module Legato
|
|
91
97
|
end
|
92
98
|
|
93
99
|
def apply_basic_options(options)
|
94
|
-
[:sort, :limit, :offset, :start_date, :end_date, :quota_user, :sampling_level].each do |key| #:segment
|
100
|
+
[:sort, :limit, :offset, :start_date, :end_date, :quota_user, :user_ip, :sampling_level, :segment_id].each do |key| #:segment
|
95
101
|
self.send("#{key}=".to_sym, options[key]) if options.has_key?(key)
|
96
102
|
end
|
97
103
|
end
|
@@ -189,9 +195,9 @@ module Legato
|
|
189
195
|
"sessions::condition::#{segment_filters.to_params}" if segment_filters.any?
|
190
196
|
end
|
191
197
|
|
192
|
-
|
193
|
-
|
194
|
-
|
198
|
+
def segment_id=(segment_id)
|
199
|
+
@segment_id = "gaid::#{segment_id}"
|
200
|
+
end
|
195
201
|
|
196
202
|
def profile_id
|
197
203
|
profile && Legato.to_ga_string(profile.id)
|
@@ -213,10 +219,11 @@ module Legato
|
|
213
219
|
'end-date' => Legato.format_time(end_date),
|
214
220
|
'max-results' => limit,
|
215
221
|
'start-index' => offset,
|
216
|
-
'segment' => segment,
|
222
|
+
'segment' => segment_id || segment,
|
217
223
|
'filters' => filters.to_params, # defaults to AND filtering
|
218
224
|
'fields' => REQUEST_FIELDS,
|
219
225
|
'quotaUser' => quota_user,
|
226
|
+
'userIp' => user_ip,
|
220
227
|
'samplingLevel' => sampling_level
|
221
228
|
}
|
222
229
|
|
@@ -228,11 +235,23 @@ module Legato
|
|
228
235
|
end
|
229
236
|
|
230
237
|
def to_query_string
|
231
|
-
|
232
|
-
|
238
|
+
to_params.map {|k,v| [k,v].join("=")}.join("&")
|
239
|
+
end
|
240
|
+
|
241
|
+
def base_url
|
242
|
+
raise "invalid tracking_scope" unless tracking_scope_valid?
|
243
|
+
|
244
|
+
endpoint = VALID_TRACKING_SCOPES[tracking_scope]
|
245
|
+
|
246
|
+
"https://www.googleapis.com/analytics/v3/data/#{endpoint}"
|
233
247
|
end
|
234
248
|
|
235
249
|
private
|
250
|
+
|
251
|
+
def tracking_scope_valid?
|
252
|
+
VALID_TRACKING_SCOPES.keys.include?(tracking_scope)
|
253
|
+
end
|
254
|
+
|
236
255
|
def request_for_query
|
237
256
|
profile.user.request(self)
|
238
257
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Legato
|
2
|
+
class Request
|
3
|
+
attr_reader :user, :query
|
4
|
+
|
5
|
+
def initialize(user, query)
|
6
|
+
@user = user
|
7
|
+
@query = query
|
8
|
+
end
|
9
|
+
|
10
|
+
def response(url = nil)
|
11
|
+
Legato::Response.new(raw_response, query.instance_klass)
|
12
|
+
end
|
13
|
+
|
14
|
+
def raw_response
|
15
|
+
api_key? ? oauth_1_response : oauth_2_response
|
16
|
+
end
|
17
|
+
|
18
|
+
def api_key?
|
19
|
+
!user.api_key.nil?
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
def oauth_2_response
|
24
|
+
# oauth 2
|
25
|
+
get(query.base_url, :params => query.to_params)
|
26
|
+
end
|
27
|
+
|
28
|
+
def oauth_1_response
|
29
|
+
# oauth 1 + api key
|
30
|
+
get(query.base_url + query_string)
|
31
|
+
end
|
32
|
+
|
33
|
+
def get(*args)
|
34
|
+
user.access_token.get(*args)
|
35
|
+
end
|
36
|
+
|
37
|
+
def query_string
|
38
|
+
# may need to add !~@
|
39
|
+
[api_key_string, URI.escape(query.to_query_string, '<>')].compact.join('&')
|
40
|
+
end
|
41
|
+
|
42
|
+
def api_key_string
|
43
|
+
"?key=#{user.api_key}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/legato/response.rb
CHANGED
@@ -21,6 +21,14 @@ module Legato
|
|
21
21
|
Hash[data["totalsForAllResults"].map{|k,v| [Legato.from_ga_string(k), number_for(v)]}]
|
22
22
|
end
|
23
23
|
|
24
|
+
def rows
|
25
|
+
Array.wrap(data['rows']).compact
|
26
|
+
end
|
27
|
+
|
28
|
+
def items
|
29
|
+
Array.wrap(data['items']).compact
|
30
|
+
end
|
31
|
+
|
24
32
|
private
|
25
33
|
def headers
|
26
34
|
data['columnHeaders']
|
@@ -30,10 +38,6 @@ module Legato
|
|
30
38
|
headers.map {|header| Legato.from_ga_string(header['name'])}
|
31
39
|
end
|
32
40
|
|
33
|
-
def rows
|
34
|
-
Array.wrap(data['rows']).compact
|
35
|
-
end
|
36
|
-
|
37
41
|
def raw_attributes
|
38
42
|
rows.map {|row| Hash[fields.zip(row)]}
|
39
43
|
end
|
data/lib/legato/user.rb
CHANGED
@@ -1,12 +1,6 @@
|
|
1
1
|
module Legato
|
2
2
|
class User
|
3
|
-
attr_accessor :access_token, :api_key
|
4
|
-
|
5
|
-
VALID_TRACKING_SCOPES = {
|
6
|
-
'ga' => 'ga',
|
7
|
-
'mcf' => 'mcf',
|
8
|
-
'rt' => 'realtime'
|
9
|
-
}
|
3
|
+
attr_accessor :access_token, :api_key, :quota_user, :user_ip
|
10
4
|
|
11
5
|
def initialize(token, api_key = nil)
|
12
6
|
self.access_token = token
|
@@ -15,19 +9,9 @@ module Legato
|
|
15
9
|
|
16
10
|
# TODO: refactor into request object again
|
17
11
|
def request(query)
|
18
|
-
|
19
|
-
|
20
|
-
raw_response = if api_key
|
21
|
-
# oauth 1 + api key
|
22
|
-
query_string = URI.escape(query.to_query_string, '<>') # may need to add !~@
|
23
|
-
|
24
|
-
access_token.get(url + query_string + "&key=#{api_key}")
|
25
|
-
else
|
26
|
-
# oauth 2
|
27
|
-
access_token.get(url, :params => query.to_params)
|
28
|
-
end
|
12
|
+
append_quotas_to_query(query)
|
29
13
|
|
30
|
-
|
14
|
+
Request.new(self, query).response
|
31
15
|
end
|
32
16
|
|
33
17
|
# Management Associations
|
@@ -37,6 +21,10 @@ module Legato
|
|
37
21
|
Management::Account.all(self)
|
38
22
|
end
|
39
23
|
|
24
|
+
def account_summary
|
25
|
+
Management::AccountSummary.all(self)
|
26
|
+
end
|
27
|
+
|
40
28
|
# All the `WebProperty` records available to this user
|
41
29
|
def web_properties
|
42
30
|
Management::WebProperty.all(self)
|
@@ -57,18 +45,10 @@ module Legato
|
|
57
45
|
Management::Goal.all(self)
|
58
46
|
end
|
59
47
|
|
60
|
-
def url_for(query)
|
61
|
-
raise "invalid tracking_scope" unless tracking_scope_valid?(query.tracking_scope)
|
62
|
-
|
63
|
-
endpoint = VALID_TRACKING_SCOPES[query.tracking_scope]
|
64
|
-
|
65
|
-
"https://www.googleapis.com/analytics/v3/data/#{endpoint}"
|
66
|
-
end
|
67
|
-
|
68
48
|
private
|
69
|
-
|
70
|
-
|
71
|
-
|
49
|
+
def append_quotas_to_query(query)
|
50
|
+
query.quota_user = quota_user if quota_user
|
51
|
+
query.user_ip = user_ip if user_ip
|
72
52
|
end
|
73
53
|
end
|
74
54
|
end
|
data/lib/legato/version.rb
CHANGED
@@ -0,0 +1,170 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Legato::Management::AccountSummary do
|
4
|
+
let(:sample_dict) {
|
5
|
+
{
|
6
|
+
:id => 12345,
|
7
|
+
:kind => "analytics#accountSummary",
|
8
|
+
:name => "Account 1",
|
9
|
+
:webProperties => [
|
10
|
+
{
|
11
|
+
:kind => "analytics#webPropertySummary",
|
12
|
+
:id => "UA-1",
|
13
|
+
:name => "WebProperty1",
|
14
|
+
:internalWebPropertyId => 123,
|
15
|
+
:level => "STANDARD",
|
16
|
+
:websiteUrl => "http://www.google.com",
|
17
|
+
:profiles => [
|
18
|
+
{
|
19
|
+
:kind => "analytics#profileSummary1",
|
20
|
+
:id => 1234,
|
21
|
+
:name => "Default",
|
22
|
+
:type => "WEB1"
|
23
|
+
},
|
24
|
+
{
|
25
|
+
:kind => "analytics#profileSummary2",
|
26
|
+
:id => 1235,
|
27
|
+
:name => "Ecommerce",
|
28
|
+
:type => "WEB2"
|
29
|
+
},
|
30
|
+
{
|
31
|
+
:kind => "analytics#profileSummary3",
|
32
|
+
:id => 1236,
|
33
|
+
:name => "Testing",
|
34
|
+
:type => "WEB3"
|
35
|
+
}
|
36
|
+
]
|
37
|
+
},
|
38
|
+
{
|
39
|
+
:kind => "analytics#webPropertySummary",
|
40
|
+
:id => "UA-2",
|
41
|
+
:name => "WebProperty2",
|
42
|
+
:internalWebPropertyId => 456,
|
43
|
+
:level => "STANDARD",
|
44
|
+
:websiteUrl => "http://www.google.com",
|
45
|
+
:profiles => [
|
46
|
+
{
|
47
|
+
:kind => "analytics#profileSummary4",
|
48
|
+
:id => 1237,
|
49
|
+
:name => "Default",
|
50
|
+
:type => "WEB4"
|
51
|
+
}
|
52
|
+
]
|
53
|
+
}
|
54
|
+
]
|
55
|
+
}
|
56
|
+
}
|
57
|
+
|
58
|
+
let(:user) { stub(:api_key => nil) }
|
59
|
+
let(:account_summary) { Legato::Management::AccountSummary.new(sample_dict, user) }
|
60
|
+
|
61
|
+
def self.subject_class_name
|
62
|
+
"account_summary"
|
63
|
+
end
|
64
|
+
|
65
|
+
context "The AccountSummary class" do
|
66
|
+
it_behaves_like "a management finder"
|
67
|
+
|
68
|
+
it 'has the correct paths' do
|
69
|
+
Legato::Management::AccountSummary.default_path.should == '/accountSummaries'
|
70
|
+
Legato::Management::AccountSummary.new(sample_dict, user).path.should == ''
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'creates a new account summary instance from a hash of attributes' do
|
74
|
+
account_summary.user.should == user
|
75
|
+
account_summary.account.class == Legato::Management::Account
|
76
|
+
account_summary.web_properties.first.class == Legato::Management::WebProperty
|
77
|
+
account_summary.profiles.first.class == Legato::Management::Profile
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
context "builds proper instances" do
|
82
|
+
it 'builds the account instance' do
|
83
|
+
account_summary.account.id.should == 12345
|
84
|
+
account_summary.account.name.should == "Account 1"
|
85
|
+
account_summary.account.user.should == user
|
86
|
+
end
|
87
|
+
|
88
|
+
it "builds the web_properties instances" do
|
89
|
+
account_summary.web_properties.size.should == 2
|
90
|
+
account_summary.web_properties.first.attributes[:kind].should == "analytics#webPropertySummary"
|
91
|
+
account_summary.web_properties.first.id.should == "UA-1"
|
92
|
+
account_summary.web_properties.first.name.should == "WebProperty1"
|
93
|
+
account_summary.web_properties.first.account_id.should == 12345
|
94
|
+
account_summary.web_properties.first.attributes[:internalWebPropertyId].should == 123
|
95
|
+
account_summary.web_properties.first.attributes[:level].should == "STANDARD"
|
96
|
+
account_summary.web_properties.last.attributes[:kind].should == "analytics#webPropertySummary"
|
97
|
+
account_summary.web_properties.last.id.should == "UA-2"
|
98
|
+
account_summary.web_properties.last.name.should == "WebProperty2"
|
99
|
+
account_summary.web_properties.last.account_id.should == 12345
|
100
|
+
account_summary.web_properties.last.attributes[:internalWebPropertyId].should == 456
|
101
|
+
account_summary.web_properties.last.attributes[:level].should == "STANDARD"
|
102
|
+
end
|
103
|
+
|
104
|
+
it "builds the profiles" do
|
105
|
+
account_summary.profiles.size.should == 4
|
106
|
+
account_summary.profiles[0].attributes[:kind].should == "analytics#profileSummary1"
|
107
|
+
account_summary.profiles[0].id.should == 1234
|
108
|
+
account_summary.profiles[0].name.should == "Default"
|
109
|
+
account_summary.profiles[0].account_id.should == 12345
|
110
|
+
account_summary.profiles[0].web_property_id.should == "UA-1"
|
111
|
+
account_summary.profiles[0].attributes[:type].should == "WEB1"
|
112
|
+
account_summary.profiles[1].attributes[:kind].should == "analytics#profileSummary2"
|
113
|
+
account_summary.profiles[1].id.should == 1235
|
114
|
+
account_summary.profiles[1].name.should == "Ecommerce"
|
115
|
+
account_summary.profiles[1].account_id.should == 12345
|
116
|
+
account_summary.profiles[1].web_property_id.should == "UA-1"
|
117
|
+
account_summary.profiles[1].attributes[:type].should == "WEB2"
|
118
|
+
account_summary.profiles[2].attributes[:kind].should == "analytics#profileSummary3"
|
119
|
+
account_summary.profiles[2].id.should == 1236
|
120
|
+
account_summary.profiles[2].name.should == "Testing"
|
121
|
+
account_summary.profiles[2].account_id.should == 12345
|
122
|
+
account_summary.profiles[2].web_property_id.should == "UA-1"
|
123
|
+
account_summary.profiles[2].attributes[:type].should == "WEB3"
|
124
|
+
account_summary.profiles[3].attributes[:kind].should == "analytics#profileSummary4"
|
125
|
+
account_summary.profiles[3].id.should == 1237
|
126
|
+
account_summary.profiles[3].name.should == "Default"
|
127
|
+
account_summary.profiles[3].account_id.should == 12345
|
128
|
+
account_summary.profiles[3].web_property_id.should == "UA-2"
|
129
|
+
account_summary.profiles[3].attributes[:type].should == "WEB4"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
context "allows forward and reverse traversing" do
|
134
|
+
it "can be used for reverse traversing to web_property from profiles" do
|
135
|
+
account_summary.profiles[0].web_property.should == account_summary.web_properties[0]
|
136
|
+
account_summary.profiles[1].web_property.should == account_summary.web_properties[0]
|
137
|
+
account_summary.profiles[2].web_property.should == account_summary.web_properties[0]
|
138
|
+
account_summary.profiles[3].web_property.should == account_summary.web_properties[1]
|
139
|
+
end
|
140
|
+
|
141
|
+
it "can be used for reverse traversing to account from profiles" do
|
142
|
+
account_summary.profiles[0].account.should == account_summary.account
|
143
|
+
account_summary.profiles[1].account.should == account_summary.account
|
144
|
+
account_summary.profiles[2].account.should == account_summary.account
|
145
|
+
account_summary.profiles[3].account.should == account_summary.account
|
146
|
+
end
|
147
|
+
|
148
|
+
it "can be used for reverse traversing to account from web_properties" do
|
149
|
+
account_summary.web_properties[0].account.should == account_summary.account
|
150
|
+
account_summary.web_properties[1].account.should == account_summary.account
|
151
|
+
end
|
152
|
+
|
153
|
+
it "can be used for traversing to profiles from web_properties" do
|
154
|
+
account_summary.web_properties[0].profiles.size.should == 3
|
155
|
+
account_summary.web_properties[0].profiles[0].id.should == 1234
|
156
|
+
account_summary.web_properties[0].profiles[1].id.should == 1235
|
157
|
+
account_summary.web_properties[0].profiles[2].id.should == 1236
|
158
|
+
account_summary.web_properties[1].profiles.size.should == 1
|
159
|
+
account_summary.web_properties[1].profiles[0].id.should == 1237
|
160
|
+
end
|
161
|
+
|
162
|
+
it "can be used for traversing to web_properties from accounts" do
|
163
|
+
account_summary.account.web_properties.should == account_summary.web_properties
|
164
|
+
end
|
165
|
+
|
166
|
+
it "can be used for traversing to profiles from accounts" do
|
167
|
+
account_summary.account.profiles.should == account_summary.profiles
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
@@ -323,6 +323,12 @@ describe Legato::Query do
|
|
323
323
|
@query.quota_user.should == 'an id'
|
324
324
|
end
|
325
325
|
|
326
|
+
it "sets the segment_id" do
|
327
|
+
segment_id = '123122534'
|
328
|
+
@query.apply_options({:segment_id => segment_id})
|
329
|
+
@query.segment_id.should == "gaid::#{segment_id}"
|
330
|
+
end
|
331
|
+
|
326
332
|
context "with Time" do
|
327
333
|
before :each do
|
328
334
|
@now = Time.now
|
@@ -354,6 +360,28 @@ describe Legato::Query do
|
|
354
360
|
end
|
355
361
|
end
|
356
362
|
|
363
|
+
context "with the scope set" do
|
364
|
+
it 'raises when an invalid scope is passed in' do
|
365
|
+
@query.tracking_scope = "what"
|
366
|
+
expect { @query.base_url }.to raise_error
|
367
|
+
end
|
368
|
+
|
369
|
+
it 'sets the correct endpoint url' do
|
370
|
+
@query.tracking_scope = "mcf"
|
371
|
+
expect(@query.base_url).to eql("https://www.googleapis.com/analytics/v3/data/mcf")
|
372
|
+
end
|
373
|
+
|
374
|
+
it 'has the correct api endpoint' do
|
375
|
+
@query.tracking_scope = "ga"
|
376
|
+
expect(@query.base_url).to eql("https://www.googleapis.com/analytics/v3/data/ga")
|
377
|
+
end
|
378
|
+
|
379
|
+
it 'has the realtime api endpoint' do
|
380
|
+
@query.tracking_scope = "rt"
|
381
|
+
expect(@query.base_url).to eql("https://www.googleapis.com/analytics/v3/data/realtime")
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
357
385
|
it_defines_operators :eql, :not_eql, :gt, :gte, :lt, :lte, :matches,
|
358
386
|
:does_not_match, :contains, :does_not_contain, :substring, :not_substring
|
359
387
|
|
@@ -439,6 +467,20 @@ describe Legato::Query do
|
|
439
467
|
@query.to_params['segment'].should == 'sessions::condition::ga::parameter'
|
440
468
|
end
|
441
469
|
|
470
|
+
it 'includes segment_id' do
|
471
|
+
@query.stubs(:segment_id).returns('gaid::12453453')
|
472
|
+
|
473
|
+
@query.to_params['segment'].should == 'gaid::12453453'
|
474
|
+
end
|
475
|
+
|
476
|
+
it 'includes segment_id and segment_filters' do
|
477
|
+
segment_filters = stub(:to_params => 'ga::parameter', :any? => true)
|
478
|
+
@query.stubs(:segment_filters).returns(segment_filters)
|
479
|
+
@query.stubs(:segment_id).returns('gaid::12453453')
|
480
|
+
|
481
|
+
@query.to_params['segment'].should == 'gaid::12453453'
|
482
|
+
end
|
483
|
+
|
442
484
|
it 'includes metrics' do
|
443
485
|
metrics = Legato::ListParameter.new(:metrics)
|
444
486
|
metrics.stubs(:to_params).returns({'metrics' => 'pageviews,exits'})
|
@@ -1,76 +1,75 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Legato::User do
|
4
|
-
context "an instance of Legato::User
|
5
|
-
let(:
|
4
|
+
context "an instance of Legato::User" do
|
5
|
+
let(:instance_klass) { Class.new }
|
6
|
+
let(:klass) { Class.new.tap {|k| k.extend(Legato::Model)} }
|
7
|
+
let(:query) { Legato::Query.new(klass) }
|
8
|
+
let(:access_token) { stub }
|
9
|
+
let(:user) { Legato::User.new(access_token) }
|
6
10
|
|
7
|
-
before
|
8
|
-
|
11
|
+
before(:each) do
|
12
|
+
query.stubs(:instance_klass).returns(instance_klass)
|
9
13
|
end
|
10
14
|
|
11
|
-
it '
|
12
|
-
|
13
|
-
end
|
15
|
+
it 'assigns a quota user to the query' do
|
16
|
+
Legato::Request.stubs(:new).returns(stub(:response => 'response'))
|
14
17
|
|
15
|
-
|
16
|
-
user.
|
17
|
-
end
|
18
|
-
end
|
18
|
+
user.quota_user = 'user12345678'
|
19
|
+
user.request(query)
|
19
20
|
|
20
|
-
|
21
|
-
before :each do
|
22
|
-
@access_token = stub
|
23
|
-
@user = Legato::User.new(@access_token)
|
21
|
+
expect(query.to_params['quotaUser']).to eql('user12345678')
|
24
22
|
end
|
25
23
|
|
26
|
-
it '
|
27
|
-
|
28
|
-
|
24
|
+
it 'assigns a user ip to the query' do
|
25
|
+
Legato::Request.stubs(:new).returns(stub(:response => 'response'))
|
26
|
+
|
27
|
+
user.user_ip = '127.0.0.1'
|
28
|
+
user.request(query)
|
29
29
|
|
30
|
-
|
31
|
-
@user.url_for(stub(:tracking_scope => 'rt')).should == "https://www.googleapis.com/analytics/v3/data/realtime"
|
30
|
+
expect(query.to_params['userIp']).to eql('127.0.0.1')
|
32
31
|
end
|
33
32
|
|
34
33
|
it 'returns a response for a given query' do
|
35
|
-
|
36
|
-
|
34
|
+
query.stubs(:to_params).returns('params')
|
35
|
+
access_token.stubs(:get).returns('a response')
|
37
36
|
Legato::Response.stubs(:new)
|
38
|
-
|
37
|
+
query.stubs(:base_url).returns("the_api_url")
|
39
38
|
|
40
|
-
|
39
|
+
user.request(query)
|
41
40
|
|
42
|
-
Legato::Response.should have_received(:new).with('a response',
|
43
|
-
|
41
|
+
Legato::Response.should have_received(:new).with('a response', instance_klass)
|
42
|
+
access_token.should have_received(:get).with("the_api_url", :params => "params")
|
44
43
|
end
|
45
44
|
|
46
45
|
it 'has accounts' do
|
47
46
|
Legato::Management::Account.stubs(:all)
|
48
|
-
|
49
|
-
Legato::Management::Account.should have_received(:all).with(
|
47
|
+
user.accounts
|
48
|
+
Legato::Management::Account.should have_received(:all).with(user)
|
50
49
|
end
|
51
50
|
|
52
51
|
it 'has web_properties' do
|
53
52
|
Legato::Management::WebProperty.stubs(:all)
|
54
|
-
|
55
|
-
Legato::Management::WebProperty.should have_received(:all).with(
|
53
|
+
user.web_properties
|
54
|
+
Legato::Management::WebProperty.should have_received(:all).with(user)
|
56
55
|
end
|
57
56
|
|
58
57
|
it 'has profiles' do
|
59
58
|
Legato::Management::Profile.stubs(:all)
|
60
|
-
|
61
|
-
Legato::Management::Profile.should have_received(:all).with(
|
59
|
+
user.profiles
|
60
|
+
Legato::Management::Profile.should have_received(:all).with(user)
|
62
61
|
end
|
63
62
|
|
64
63
|
it 'has segments' do
|
65
64
|
Legato::Management::Segment.stubs(:all)
|
66
|
-
|
67
|
-
Legato::Management::Segment.should have_received(:all).with(
|
65
|
+
user.segments
|
66
|
+
Legato::Management::Segment.should have_received(:all).with(user)
|
68
67
|
end
|
69
68
|
|
70
69
|
it 'has goals' do
|
71
70
|
Legato::Management::Goal.stubs(:all)
|
72
|
-
|
73
|
-
Legato::Management::Goal.should have_received(:all).with(
|
71
|
+
user.goals
|
72
|
+
Legato::Management::Goal.should have_received(:all).with(user)
|
74
73
|
end
|
75
74
|
end
|
76
75
|
end
|
@@ -1,16 +1,9 @@
|
|
1
1
|
shared_examples_for "a management finder" do
|
2
2
|
let(:response) { stub(:body => 'some json') }
|
3
3
|
let(:access_token) { stub(:get => response) }
|
4
|
-
let(:user) {
|
4
|
+
let(:user) { Legato::User.new(access_token, nil) }
|
5
5
|
|
6
6
|
context ".all" do
|
7
|
-
after do
|
8
|
-
user.should have_received(:access_token)
|
9
|
-
access_token.should have_received(:get).with('https://www.googleapis.com/analytics/v3/management'+described_class.default_path)
|
10
|
-
response.should have_received(:body)
|
11
|
-
MultiJson.should have_received(:decode).with('some json')
|
12
|
-
end
|
13
|
-
|
14
7
|
it "returns an array of all #{subject_class_name} available to a user" do
|
15
8
|
MultiJson.stubs(:decode).returns({'items' => ['item1', 'item2']})
|
16
9
|
described_class.stubs(:new).returns('thing1', 'thing2')
|
@@ -19,6 +12,10 @@ shared_examples_for "a management finder" do
|
|
19
12
|
|
20
13
|
described_class.should have_received(:new).with('item1', user)
|
21
14
|
described_class.should have_received(:new).with('item2', user)
|
15
|
+
|
16
|
+
access_token.should have_received(:get).with('https://www.googleapis.com/analytics/v3/management'+described_class.default_path, :params => {})
|
17
|
+
response.should have_received(:body)
|
18
|
+
MultiJson.should have_received(:decode).with('some json')
|
22
19
|
end
|
23
20
|
|
24
21
|
it "returns an empty array of #{subject_class_name} when there are no results" do
|
@@ -30,13 +27,6 @@ shared_examples_for "a management finder" do
|
|
30
27
|
end
|
31
28
|
|
32
29
|
context ".get" do
|
33
|
-
after do
|
34
|
-
user.should have_received(:access_token)
|
35
|
-
access_token.should have_received(:get).with('https://www.googleapis.com/analytics/v3/management/path')
|
36
|
-
response.should have_received(:body)
|
37
|
-
MultiJson.should have_received(:decode).with('some json')
|
38
|
-
end
|
39
|
-
|
40
30
|
it "returns an instance of #{subject_class_name} for a given path" do
|
41
31
|
MultiJson.stubs(:decode).returns('attributes')
|
42
32
|
described_class.stubs(:new).returns('thing')
|
@@ -45,6 +35,10 @@ shared_examples_for "a management finder" do
|
|
45
35
|
|
46
36
|
expect(described_class.get(user, path)).to eq('thing')
|
47
37
|
expect(described_class).to have_received(:new).with('attributes', user)
|
38
|
+
|
39
|
+
access_token.should have_received(:get).with('https://www.googleapis.com/analytics/v3/management/path', :params => {})
|
40
|
+
response.should have_received(:body)
|
41
|
+
MultiJson.should have_received(:decode).with('some json')
|
48
42
|
end
|
49
43
|
end
|
50
|
-
end
|
44
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: legato
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tony Pitale
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-09-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -137,6 +137,7 @@ files:
|
|
137
137
|
- ".ruby-version"
|
138
138
|
- ".travis.yml"
|
139
139
|
- CHANGELOG.md
|
140
|
+
- CODE_OF_CONDUCT.md
|
140
141
|
- Gemfile
|
141
142
|
- README.md
|
142
143
|
- Rakefile
|
@@ -150,14 +151,17 @@ files:
|
|
150
151
|
- lib/legato/filter_set.rb
|
151
152
|
- lib/legato/list_parameter.rb
|
152
153
|
- lib/legato/management/account.rb
|
154
|
+
- lib/legato/management/account_summary.rb
|
153
155
|
- lib/legato/management/finder.rb
|
154
156
|
- lib/legato/management/goal.rb
|
155
157
|
- lib/legato/management/profile.rb
|
158
|
+
- lib/legato/management/query.rb
|
156
159
|
- lib/legato/management/segment.rb
|
157
160
|
- lib/legato/management/web_property.rb
|
158
161
|
- lib/legato/model.rb
|
159
162
|
- lib/legato/profile_methods.rb
|
160
163
|
- lib/legato/query.rb
|
164
|
+
- lib/legato/request.rb
|
161
165
|
- lib/legato/response.rb
|
162
166
|
- lib/legato/user.rb
|
163
167
|
- lib/legato/version.rb
|
@@ -173,6 +177,7 @@ files:
|
|
173
177
|
- spec/lib/legato/legato_spec.rb
|
174
178
|
- spec/lib/legato/list_parameter_spec.rb
|
175
179
|
- spec/lib/legato/management/account_spec.rb
|
180
|
+
- spec/lib/legato/management/account_summary_spec.rb
|
176
181
|
- spec/lib/legato/management/goal_spec.rb
|
177
182
|
- spec/lib/legato/management/legato_spec.rb
|
178
183
|
- spec/lib/legato/management/profile_spec.rb
|
@@ -221,6 +226,7 @@ test_files:
|
|
221
226
|
- spec/lib/legato/legato_spec.rb
|
222
227
|
- spec/lib/legato/list_parameter_spec.rb
|
223
228
|
- spec/lib/legato/management/account_spec.rb
|
229
|
+
- spec/lib/legato/management/account_summary_spec.rb
|
224
230
|
- spec/lib/legato/management/goal_spec.rb
|
225
231
|
- spec/lib/legato/management/legato_spec.rb
|
226
232
|
- spec/lib/legato/management/profile_spec.rb
|