Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[137] GA API V4 #141

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .ruby-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.0.1
3.0.2
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ rvm:
- 2.2.2
- 2.6.7
- 2.7.3
- 3.0.1
- 3.0.2
script: bundle exec rspec spec
notifications:
webhooks:
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ You can also call `realtime` on your model to get a new `Query` instance with re
```ruby
query = Exit.realtime
query.realtime? #=> true
query.tracking_scope #=> 'rt'
query.tracking_scope #=> 'realtime'
```

## Managing Quotas ##
Expand Down
5 changes: 2 additions & 3 deletions lib/legato.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,10 @@ def self.or_join_character
end
end

require 'legato/request'
require 'legato/core'
require 'legato/user'
require 'legato/profile_methods'
require 'legato/request_formatters'

require 'legato/management/model'
require 'legato/management/query'
Expand All @@ -57,8 +58,6 @@ def self.or_join_character
require 'legato/management/goal'

require 'legato/list_parameter'
require 'legato/response'
require 'legato/filter'
require 'legato/filter_set'
require 'legato/query'
require 'legato/model'
8 changes: 8 additions & 0 deletions lib/legato/core.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module Legato
module Core
end
end

require 'legato/core/request'
require 'legato/core/response'
require 'legato/core/query'
63 changes: 45 additions & 18 deletions lib/legato/query.rb → lib/legato/core/query.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module Legato
module Legato::Core
class Query
include Enumerable

Expand Down Expand Up @@ -32,7 +32,7 @@ def self.define_filter_operators(*methods)
methods.each do |method|
class_eval <<-CODE
def #{method}(field, value, join_character=nil)
Filter.new(self, field, :#{method}, value, join_character)
Legato::Filter.new(self, field, :#{method}, value, join_character)
end
CODE
end
Expand All @@ -42,13 +42,13 @@ def #{method}(field, value, join_character=nil)
attr_accessor :profile, :start_date, :end_date
attr_accessor :sort, :limit, :offset, :quota_user, :user_ip, :sampling_level, :segment_id #, :segment # individual, overwritten
attr_accessor :filters, :segment_filters # combined, can be appended to
attr_accessor :tracking_scope
attr_writer :tracking_scope

def self.from_query(query)
new(query.parent_klass, query.tracking_scope, query.filters, query.segment_filters)
end

def initialize(klass, tracking_scope = "ga", filters = FilterSet.new, segment_filters = FilterSet.new)
def initialize(klass, tracking_scope = "ga", filters = Legato::FilterSet.new, segment_filters = Legato::FilterSet.new)
@loaded = false
@parent_klass = klass
self.filters = filters
Expand All @@ -70,6 +70,14 @@ def instance_klass
@parent_klass.instance_klass
end

def tracking_scope
VALID_TRACKING_SCOPES[@tracking_scope]
end

def tracking_scope_valid?
VALID_TRACKING_SCOPES.keys.include?(@tracking_scope)
end

def apply_filter(*args, &block)
apply_filter_expression(self.filters, *args, &block)
end
Expand Down Expand Up @@ -139,12 +147,12 @@ def basic_options
# field, operator = key, :eql
# field, operator = key.target, key.operator if key.is_a?(SymbolOperatorMethods)

# Filter.new(field, operator, value, join_character)
# Legato::Filter.new(field, operator, value, join_character)
# end

def extract_profile(args)
return args.shift if args.first.is_a?(Management::Profile)
return args.pop if args.last.is_a?(Management::Profile)
return args.shift if args.first.is_a?(Legato::Management::Profile)
return args.pop if args.last.is_a?(Legato::Management::Profile)
profile
end

Expand Down Expand Up @@ -233,7 +241,7 @@ def profile_id
end

def realtime?
tracking_scope == 'rt'
@tracking_scope == 'rt'
end

def realtime
Expand All @@ -251,16 +259,39 @@ def to_params
end
end

# V3
def to_query_string
to_params.map {|k,v| [k,v].join("=")}.join("&")
end

def base_url
raise "invalid tracking_scope" unless tracking_scope_valid?

endpoint = VALID_TRACKING_SCOPES[tracking_scope]

"https://www.googleapis.com/analytics/v3/data/#{endpoint}"
# V4
# TODO: extract to formatter class
def to_body
{
# TODO: support batch of requests by passing >1
reportRequests: [
{
viewId: profile_id,
# TODO: support >1 date ranges
dateRanges: [
{
startDate: Legato.format_time(start_date),
endDate: Legato.format_time(end_date)
}
],
metrics: metrics.to_report_format,
dimensions: dimensions.to_report_format,
orderBys: sort.to_report_format,
samplingLevel: sampling_level
# segments: [],
# TODO: filters are wildly different
# filters: filters.to_report_format
# includeEmptyRows: include_empty_rows
# pageSize
# pageToken
}.reject{|_,v| v.nil?}
]
}
end

private
Expand All @@ -281,10 +312,6 @@ def base_params
}.reject! {|_,v| v.nil? || v.to_s.strip.length == 0}
end

def tracking_scope_valid?
VALID_TRACKING_SCOPES.keys.include?(tracking_scope)
end

def request_for_query
profile.user.request(self)
end
Expand Down
15 changes: 15 additions & 0 deletions lib/legato/core/request.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
require_relative 'v3/request'
require_relative 'v4/request'

module Legato::Core
class Request
def self.[](version)
case version
when 3
V3::Request
when 4
V4::Request
end
end
end
end
15 changes: 15 additions & 0 deletions lib/legato/core/response.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
require_relative 'v3/response'
require_relative 'v4/response'

module Legato::Core
class Response
def self.[](version)
case version
when 3
V3::Response
when 4
V4::Response
end
end
end
end
17 changes: 13 additions & 4 deletions lib/legato/request.rb → lib/legato/core/v3/request.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module Legato
module Legato::Core::V3
class Request
attr_reader :user, :query

Expand All @@ -8,7 +8,7 @@ def initialize(user, query)
end

def response(url = nil)
Legato::Response.new(raw_response, query.instance_klass)
Legato::Core::V3::Response.new(raw_response, query.instance_klass)
end

def raw_response
Expand All @@ -19,15 +19,24 @@ def api_key?
!user.api_key.nil?
end

def base_url
# Handle management API queries
return query.base_url if query.respond_to?(:base_url)

raise "invalid tracking_scope" unless query.tracking_scope_valid?

"https://www.googleapis.com/analytics/v3/data/#{query.tracking_scope}"
end

private
def oauth_2_response
# oauth 2
get(query.base_url, :params => query.to_params)
get(base_url, :params => query.to_params)
end

def oauth_1_response
# oauth 1 + api key
get(query.base_url + query_string)
get(base_url + query_string)
end

def get(*args)
Expand Down
2 changes: 1 addition & 1 deletion lib/legato/response.rb → lib/legato/core/v3/response.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module Legato
module Legato::Core::V3
class Response
def initialize(raw_response, instance_klass = OpenStruct)
@raw_response = raw_response
Expand Down
22 changes: 22 additions & 0 deletions lib/legato/core/v4/report_row.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module Legato::Core::V4
class ReportRow
def initialize(raw_row, fields)
@dimensions = raw_row.fetch('dimensions', [])

# TODO: handle an optional second date range?
first_metric = raw_row.fetch('metrics', []).first || {}
@metrics = first_metric.fetch('values', [])

@fields = fields
end

def to_h
Hash[@fields.zip(row)]
end

private
def row
@dimensions.concat(@metrics)
end
end
end
49 changes: 49 additions & 0 deletions lib/legato/core/v4/request.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
module Legato::Core::V4
class Request
attr_reader :user, :query

def initialize(user, query)
@user = user
@query = query
end

def response(url = nil)
Legato::Core::V4::Response.new(raw_response, query.instance_klass)
end

def raw_response
# oauth 2
post(base_url, :body => query.to_body)
end

# def api_key?
# !user.api_key.nil?
# end

private
# def oauth_2_response
# end

# def oauth_1_response
# # oauth 1 + api key
# post(base_url + query_string)
# end

def base_url
"https://analyticsreporting.googleapis.com/v4/reports:batchGet"
end

def post(*args)
user.access_token.post(*args)
end

# def query_string
# # may need to add !~@
# [api_key_string, URI.escape(query.to_query_string, '<>')].compact.join('&')
# end

# def api_key_string
# "?key=#{user.api_key}"
# end
end
end
Loading