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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d8b3ba1c16166742956642f4a56d653a1ef29979
4
- data.tar.gz: d78953dc68eb6334f49d88cb283ce786702ee942
3
+ metadata.gz: 980eb1079898deac8afc471a03804fda0cc3865a
4
+ data.tar.gz: 90eb6e06d3ccfb0ebb5cb178c8e81ef9808beef6
5
5
  SHA512:
6
- metadata.gz: 4932242d29976df1b52c3289377f2f686d3e9fe2d6f54f290217a8f55db956d2737b35b81457fb20a60a74554f3b00e59aad90728cafb3868e16b1b8128243da
7
- data.tar.gz: 5db330c1e6397053c566adffb26c58cc145d0a536965c78a1e0b28484addbeb24c2d3396bdb4c2ad07502b5a9dab67e2cb51ca9c955b71051f9c92f871c4df1c
6
+ metadata.gz: bdb333f5453cb364f28a431eb1b6b84cf3c8fedd1df39a05e3af0bf6784cda44e9279b2e81051d81158daa5717cc8ed7a6ce2786deed0b59e180266acb66ef0b
7
+ data.tar.gz: 6596be013de3f10f9704e9ab11167316d475919038200770f34130b99dc555218905420c7cd36a000bba44db4926b054797ba3ef497ee7bda2f3b28a3d79bb1b
@@ -1 +1 @@
1
- 1.9.3
1
+ 2.2.2
@@ -1,4 +1,5 @@
1
1
  language: ruby
2
+ sudo: false
2
3
  rvm:
3
4
  - 1.9.2
4
5
  - 1.9.3
@@ -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`
@@ -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)
@@ -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
- Profile.for_account(self)
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
- uri = uri_for_user(user, path)
9
+ query = Legato::Management::Query.new(base_uri + path, self)
10
10
 
11
- json = user.access_token.get(uri).body
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
- uri = uri_for_user(user, path)
18
- json = user.access_token.get(uri).body
15
+ query = Legato::Management::Query.new(base_uri + path, self)
19
16
 
20
- new(MultiJson.decode(json), user)
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
@@ -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
@@ -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
- # def segment_id
193
- # segment.nil? ? nil : "gaid::#{segment}"
194
- # end
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
- list = to_params.map {|k,v| [k,v].join("=")}
232
- "?#{list.join("&")}"
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
@@ -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
@@ -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
- url = url_for(query)
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
- Response.new(raw_response, query.instance_klass)
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
- def tracking_scope_valid?(tracking_scope)
71
- VALID_TRACKING_SCOPES.keys.include?(tracking_scope)
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
@@ -1,3 +1,3 @@
1
1
  module Legato
2
- VERSION = "0.5.1"
2
+ VERSION = "0.5.2"
3
3
  end
@@ -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 with the scope set" do
5
- let(:user) {user = Legato::User.new(@access_token, nil)}
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 :each do
8
- @access_token = stub
11
+ before(:each) do
12
+ query.stubs(:instance_klass).returns(instance_klass)
9
13
  end
10
14
 
11
- it 'raises when an invalid scope is passed in' do
12
- expect { user.url_for(stub(:tracking_scope => "what"))}.to raise_error
13
- end
15
+ it 'assigns a quota user to the query' do
16
+ Legato::Request.stubs(:new).returns(stub(:response => 'response'))
14
17
 
15
- it 'sets the correct endpoint url' do
16
- user.url_for(stub(:tracking_scope => 'mcf')).should == "https://www.googleapis.com/analytics/v3/data/mcf"
17
- end
18
- end
18
+ user.quota_user = 'user12345678'
19
+ user.request(query)
19
20
 
20
- context "an instance of Legato::User" do
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 'has the correct api endpoint' do
27
- @user.url_for(stub(:tracking_scope => 'ga')).should == "https://www.googleapis.com/analytics/v3/data/ga"
28
- end
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
- it 'has the realtime api endpoint' do
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
- klass = Class.new
36
- @access_token.stubs(:get).returns('a response')
34
+ query.stubs(:to_params).returns('params')
35
+ access_token.stubs(:get).returns('a response')
37
36
  Legato::Response.stubs(:new)
38
- @user.stubs(:url_for).returns("the_api_url")
37
+ query.stubs(:base_url).returns("the_api_url")
39
38
 
40
- @user.request(stub(:to_params => "params", :instance_klass => klass))
39
+ user.request(query)
41
40
 
42
- Legato::Response.should have_received(:new).with('a response', klass)
43
- @access_token.should have_received(:get).with("the_api_url", :params => "params")
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
- @user.accounts
49
- Legato::Management::Account.should have_received(:all).with(@user)
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
- @user.web_properties
55
- Legato::Management::WebProperty.should have_received(:all).with(@user)
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
- @user.profiles
61
- Legato::Management::Profile.should have_received(:all).with(@user)
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
- @user.segments
67
- Legato::Management::Segment.should have_received(:all).with(@user)
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
- @user.goals
73
- Legato::Management::Goal.should have_received(:all).with(@user)
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) { stub(:access_token => access_token, :api_key => nil) }
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.1
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-06-11 00:00:00.000000000 Z
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