readmedia-garb 0.9.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +198 -0
- data/Rakefile +57 -0
- data/lib/garb/account.rb +22 -0
- data/lib/garb/account_feed_request.rb +25 -0
- data/lib/garb/authentication_request.rb +53 -0
- data/lib/garb/data_request.rb +42 -0
- data/lib/garb/destination.rb +18 -0
- data/lib/garb/filter_parameters.rb +42 -0
- data/lib/garb/goal.rb +20 -0
- data/lib/garb/management/account.rb +39 -0
- data/lib/garb/management/feed.rb +26 -0
- data/lib/garb/management/goal.rb +44 -0
- data/lib/garb/management/profile.rb +44 -0
- data/lib/garb/management/segment.rb +27 -0
- data/lib/garb/management/web_property.rb +38 -0
- data/lib/garb/model.rb +91 -0
- data/lib/garb/profile.rb +33 -0
- data/lib/garb/profile_reports.rb +16 -0
- data/lib/garb/report.rb +28 -0
- data/lib/garb/report_parameter.rb +25 -0
- data/lib/garb/report_response.rb +56 -0
- data/lib/garb/reports/bounces.rb +5 -0
- data/lib/garb/reports/exits.rb +5 -0
- data/lib/garb/reports/pageviews.rb +5 -0
- data/lib/garb/reports/unique_pageviews.rb +5 -0
- data/lib/garb/reports/visits.rb +5 -0
- data/lib/garb/reports.rb +5 -0
- data/lib/garb/resource.rb +115 -0
- data/lib/garb/result_set.rb +21 -0
- data/lib/garb/session.rb +25 -0
- data/lib/garb/step.rb +13 -0
- data/lib/garb/version.rb +14 -0
- data/lib/garb.rb +69 -0
- data/lib/support.rb +40 -0
- data/test/fixtures/cacert.pem +67 -0
- data/test/fixtures/profile_feed.xml +72 -0
- data/test/fixtures/report_feed.xml +48 -0
- data/test/test_helper.rb +45 -0
- data/test/unit/garb/account_feed_request_test.rb +42 -0
- data/test/unit/garb/account_test.rb +53 -0
- data/test/unit/garb/authentication_request_test.rb +121 -0
- data/test/unit/garb/data_request_test.rb +107 -0
- data/test/unit/garb/destination_test.rb +28 -0
- data/test/unit/garb/filter_parameters_test.rb +68 -0
- data/test/unit/garb/goal_test.rb +24 -0
- data/test/unit/garb/management/account_test.rb +70 -0
- data/test/unit/garb/management/feed_test.rb +44 -0
- data/test/unit/garb/management/goal_test.rb +81 -0
- data/test/unit/garb/management/profile_test.rb +81 -0
- data/test/unit/garb/management/segment_test.rb +47 -0
- data/test/unit/garb/management/web_property_test.rb +64 -0
- data/test/unit/garb/model_test.rb +141 -0
- data/test/unit/garb/oauth_session_test.rb +11 -0
- data/test/unit/garb/profile_reports_test.rb +29 -0
- data/test/unit/garb/profile_test.rb +77 -0
- data/test/unit/garb/report_parameter_test.rb +43 -0
- data/test/unit/garb/report_response_test.rb +47 -0
- data/test/unit/garb/report_test.rb +99 -0
- data/test/unit/garb/resource_test.rb +50 -0
- data/test/unit/garb/session_test.rb +84 -0
- data/test/unit/garb/step_test.rb +15 -0
- data/test/unit/garb_test.rb +26 -0
- data/test/unit/symbol_operator_test.rb +37 -0
- metadata +189 -0
@@ -0,0 +1,38 @@
|
|
1
|
+
module Garb
|
2
|
+
module Management
|
3
|
+
class WebProperty
|
4
|
+
attr_accessor :session, :path
|
5
|
+
attr_accessor :id, :account_id
|
6
|
+
|
7
|
+
def self.all(session = Session, path='/accounts/~all/webproperties')
|
8
|
+
feed = Feed.new(session, path)
|
9
|
+
feed.entries.map {|entry| new_from_entry(entry, session)}
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.for_account(account)
|
13
|
+
all(account.session, account.path+'/webproperties')
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.new_from_entry(entry, session)
|
17
|
+
web_property = new
|
18
|
+
web_property.session = session
|
19
|
+
web_property.path = Garb.parse_link(entry, "self").gsub(Feed::BASE_URL, '')
|
20
|
+
web_property.properties = Garb.parse_properties(entry)
|
21
|
+
web_property
|
22
|
+
end
|
23
|
+
|
24
|
+
def properties=(properties)
|
25
|
+
self.id = properties["web_property_id"]
|
26
|
+
self.account_id = properties["account_id"]
|
27
|
+
end
|
28
|
+
|
29
|
+
def profiles
|
30
|
+
@profiles ||= Profile.for_web_property(self)
|
31
|
+
end
|
32
|
+
|
33
|
+
def goals
|
34
|
+
@goals ||= Goal.for_web_property(self)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/garb/model.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
module Garb
|
2
|
+
module Model
|
3
|
+
MONTH = 2592000
|
4
|
+
URL = "https://www.googleapis.com/analytics/v2.4/data"
|
5
|
+
|
6
|
+
def self.extended(base)
|
7
|
+
ProfileReports.add_report_method(base)
|
8
|
+
end
|
9
|
+
|
10
|
+
def metrics(*fields)
|
11
|
+
@metrics ||= ReportParameter.new(:metrics)
|
12
|
+
@metrics << fields
|
13
|
+
end
|
14
|
+
|
15
|
+
def dimensions(*fields)
|
16
|
+
@dimensions ||= ReportParameter.new(:dimensions)
|
17
|
+
@dimensions << fields
|
18
|
+
end
|
19
|
+
|
20
|
+
def set_instance_klass(klass)
|
21
|
+
@instance_klass = klass
|
22
|
+
end
|
23
|
+
|
24
|
+
def instance_klass
|
25
|
+
@instance_klass || OpenStruct
|
26
|
+
end
|
27
|
+
|
28
|
+
def results(profile, options = {})
|
29
|
+
start_date = options.fetch(:start_date, Time.now - MONTH)
|
30
|
+
end_date = options.fetch(:end_date, Time.now)
|
31
|
+
default_params = build_default_params(profile, start_date, end_date)
|
32
|
+
|
33
|
+
param_set = [
|
34
|
+
default_params,
|
35
|
+
metrics.to_params,
|
36
|
+
dimensions.to_params,
|
37
|
+
parse_filters(options).to_params,
|
38
|
+
parse_segment(options),
|
39
|
+
parse_sort(options).to_params,
|
40
|
+
build_page_params(options)
|
41
|
+
]
|
42
|
+
|
43
|
+
data = send_request_for_data(profile, build_params(param_set))
|
44
|
+
ReportResponse.new(data, instance_klass).results
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
def send_request_for_data(profile, params)
|
49
|
+
request = DataRequest.new(profile.session, URL, params)
|
50
|
+
response = request.send_request
|
51
|
+
response.body
|
52
|
+
end
|
53
|
+
|
54
|
+
def build_params(param_set)
|
55
|
+
param_set.inject({}) {|p,i| p.merge(i)}.reject{|k,v| v.nil?}
|
56
|
+
end
|
57
|
+
|
58
|
+
def parse_filters(options)
|
59
|
+
filters = FilterParameters.new
|
60
|
+
filters.parameters << options[:filters] if options.has_key?(:filters)
|
61
|
+
filters
|
62
|
+
end
|
63
|
+
|
64
|
+
def parse_segment(options)
|
65
|
+
segment_id = "gaid::#{options[:segment_id].to_i}" if options.has_key?(:segment_id)
|
66
|
+
{'segment' => segment_id}
|
67
|
+
end
|
68
|
+
|
69
|
+
def parse_sort(options)
|
70
|
+
sort = ReportParameter.new(:sort)
|
71
|
+
sort << options[:sort] if options.has_key?(:sort)
|
72
|
+
sort
|
73
|
+
end
|
74
|
+
|
75
|
+
def build_default_params(profile, start_date, end_date)
|
76
|
+
{
|
77
|
+
'ids' => Garb.to_ga(profile.id),
|
78
|
+
'start-date' => format_time(start_date),
|
79
|
+
'end-date' => format_time(end_date)
|
80
|
+
}
|
81
|
+
end
|
82
|
+
|
83
|
+
def build_page_params(options)
|
84
|
+
{'max-results' => options[:limit], 'start-index' => options[:offset]}
|
85
|
+
end
|
86
|
+
|
87
|
+
def format_time(t)
|
88
|
+
t.strftime('%Y-%m-%d')
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
data/lib/garb/profile.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
module Garb
|
2
|
+
class Profile
|
3
|
+
|
4
|
+
include ProfileReports
|
5
|
+
|
6
|
+
attr_reader :session, :table_id, :title, :account_name, :account_id, :web_property_id, :goals
|
7
|
+
|
8
|
+
def initialize(entry, session)
|
9
|
+
@session = session
|
10
|
+
@title = entry['title']
|
11
|
+
@table_id = entry['dxp:tableId']
|
12
|
+
@goals = (entry[Garb.to_ga('goal')] || []).map {|g| Goal.new(g)}
|
13
|
+
|
14
|
+
Garb.parse_properties(entry).each do |k,v|
|
15
|
+
instance_variable_set :"@#{k}", v
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def id
|
20
|
+
Garb.from_ga(@table_id)
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.all(session = Session)
|
24
|
+
ActiveSupport::Deprecation.warn("Garb::Profile.all is deprecated in favor of Garb::Management::Profile.all")
|
25
|
+
AccountFeedRequest.new(session).entries.map {|entry| new(entry, session)}
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.first(id, session = Session)
|
29
|
+
ActiveSupport::Deprecation.warn("Garb::Profile.first is deprecated in favor of Garb::Management::WebProperty")
|
30
|
+
all(session).detect {|profile| profile.id == id || profile.web_property_id == id }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Garb
|
2
|
+
module ProfileReports
|
3
|
+
def self.add_report_method(klass)
|
4
|
+
# demodulize leaves potential to redefine
|
5
|
+
# these methods given different namespaces
|
6
|
+
method_name = klass.name.to_s.demodulize.underscore
|
7
|
+
return unless method_name.length > 0
|
8
|
+
|
9
|
+
class_eval <<-CODE
|
10
|
+
def #{method_name}(opts = {}, &block)
|
11
|
+
#{klass}.results(self, opts, &block)
|
12
|
+
end
|
13
|
+
CODE
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/garb/report.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
module Garb
|
2
|
+
class Report
|
3
|
+
include Resource
|
4
|
+
|
5
|
+
MONTH = 2592000
|
6
|
+
URL = "https://www.google.com/analytics/feeds/data"
|
7
|
+
|
8
|
+
def initialize(profile, opts={})
|
9
|
+
ActiveSupport::Deprecation.warn("The use of Report will be removed in favor of 'extend Garb::Model'")
|
10
|
+
|
11
|
+
@profile = profile
|
12
|
+
|
13
|
+
@start_date = opts.fetch(:start_date, Time.now - MONTH)
|
14
|
+
@end_date = opts.fetch(:end_date, Time.now)
|
15
|
+
@limit = opts.fetch(:limit, nil)
|
16
|
+
@offset = opts.fetch(:offset, nil)
|
17
|
+
|
18
|
+
metrics opts.fetch(:metrics, [])
|
19
|
+
dimensions opts.fetch(:dimensions, [])
|
20
|
+
sort opts.fetch(:sort, [])
|
21
|
+
end
|
22
|
+
|
23
|
+
def results
|
24
|
+
ReportResponse.new(send_request_for_body).results
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Garb
|
2
|
+
class ReportParameter
|
3
|
+
|
4
|
+
attr_reader :elements
|
5
|
+
|
6
|
+
def initialize(name)
|
7
|
+
@name = name
|
8
|
+
@elements = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def name
|
12
|
+
@name.to_s
|
13
|
+
end
|
14
|
+
|
15
|
+
def <<(element)
|
16
|
+
(@elements += [element].flatten).compact!
|
17
|
+
self
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_params
|
21
|
+
value = self.elements.map{|param| Garb.to_google_analytics(param)}.join(',')
|
22
|
+
value.empty? ? {} : {self.name => value}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Garb
|
2
|
+
class ReportResponse
|
3
|
+
KEYS = ['dxp:metric', 'dxp:dimension']
|
4
|
+
|
5
|
+
def initialize(response_body, instance_klass = OpenStruct)
|
6
|
+
@xml = response_body
|
7
|
+
@instance_klass = instance_klass
|
8
|
+
end
|
9
|
+
|
10
|
+
def results
|
11
|
+
if @results.nil?
|
12
|
+
@results = ResultSet.new(parse)
|
13
|
+
@results.total_results = parse_total_results
|
14
|
+
@results.sampled = parse_sampled_flag
|
15
|
+
end
|
16
|
+
|
17
|
+
@results
|
18
|
+
end
|
19
|
+
|
20
|
+
def sampled?
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
def parse
|
25
|
+
entries.map do |entry|
|
26
|
+
@instance_klass.new(Hash[
|
27
|
+
values_for(entry).map {|v| [Garb.from_ga(v['name']), v['value']]}
|
28
|
+
])
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def entries
|
33
|
+
feed? ? [parsed_xml['feed']['entry']].flatten.compact : []
|
34
|
+
end
|
35
|
+
|
36
|
+
def parse_total_results
|
37
|
+
feed? ? parsed_xml['feed']['openSearch:totalResults'].to_i : 0
|
38
|
+
end
|
39
|
+
|
40
|
+
def parse_sampled_flag
|
41
|
+
feed? ? (parsed_xml['feed']['dxp:containsSampledData'] == 'true') : false
|
42
|
+
end
|
43
|
+
|
44
|
+
def parsed_xml
|
45
|
+
@parsed_xml ||= Crack::XML.parse(@xml)
|
46
|
+
end
|
47
|
+
|
48
|
+
def feed?
|
49
|
+
!parsed_xml['feed'].nil?
|
50
|
+
end
|
51
|
+
|
52
|
+
def values_for(entry)
|
53
|
+
KEYS.map {|k| entry[k]}.flatten.compact
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/garb/reports.rb
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
module Garb
|
2
|
+
module Resource
|
3
|
+
MONTH = 2592000
|
4
|
+
URL = "https://www.googleapis.com/analytics/v2.4/data"
|
5
|
+
|
6
|
+
def self.extended(base)
|
7
|
+
# define a method on a module that gets included into profile
|
8
|
+
# Exits would make:
|
9
|
+
# to enable profile.exits(options_hash, &block)
|
10
|
+
# returns Exits.results(self, options_hash, &block)
|
11
|
+
# every class defined which extends Resource will add to the module
|
12
|
+
|
13
|
+
ActiveSupport::Deprecation.warn("The use of Garb::Resource will be removed in favor of 'extend Garb::Model'")
|
14
|
+
ProfileReports.add_report_method(base)
|
15
|
+
end
|
16
|
+
|
17
|
+
%w(metrics dimensions sort).each do |parameter|
|
18
|
+
class_eval <<-CODE
|
19
|
+
def #{parameter}(*fields)
|
20
|
+
@#{parameter} ||= ReportParameter.new(:#{parameter})
|
21
|
+
@#{parameter} << fields
|
22
|
+
end
|
23
|
+
|
24
|
+
def clear_#{parameter}
|
25
|
+
@#{parameter} = ReportParameter.new(:#{parameter})
|
26
|
+
end
|
27
|
+
CODE
|
28
|
+
end
|
29
|
+
|
30
|
+
def filters(*hashes, &block)
|
31
|
+
@filter_parameters ||= FilterParameters.new
|
32
|
+
|
33
|
+
hashes.each do |hash|
|
34
|
+
@filter_parameters.parameters << hash
|
35
|
+
end
|
36
|
+
|
37
|
+
@filter_parameters.filters(&block) if block_given?
|
38
|
+
@filter_parameters
|
39
|
+
end
|
40
|
+
|
41
|
+
def clear_filters
|
42
|
+
@filter_parameters = FilterParameters.new
|
43
|
+
end
|
44
|
+
|
45
|
+
def set_segment_id(id)
|
46
|
+
@segment = "gaid::#{id.to_i}"
|
47
|
+
end
|
48
|
+
|
49
|
+
def segment
|
50
|
+
@segment
|
51
|
+
end
|
52
|
+
|
53
|
+
def set_instance_klass(klass)
|
54
|
+
@instance_klass = klass
|
55
|
+
end
|
56
|
+
|
57
|
+
def instance_klass
|
58
|
+
@instance_klass || OpenStruct
|
59
|
+
end
|
60
|
+
|
61
|
+
def results(profile, opts = {}, &block)
|
62
|
+
@profile = profile.is_a?(Profile) ? profile : Profile.first(profile, opts.fetch(:session, Session))
|
63
|
+
|
64
|
+
if @profile
|
65
|
+
@start_date = opts.fetch(:start_date, Time.now - MONTH)
|
66
|
+
@end_date = opts.fetch(:end_date, Time.now)
|
67
|
+
@limit = opts.fetch(:limit, nil)
|
68
|
+
@offset = opts.fetch(:offset, nil)
|
69
|
+
|
70
|
+
instance_eval(&block) if block_given?
|
71
|
+
|
72
|
+
ReportResponse.new(send_request_for_body, instance_klass).results
|
73
|
+
else
|
74
|
+
[]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def page_params
|
79
|
+
{'max-results' => @limit, 'start-index' => @offset}.reject{|k,v| v.nil?}
|
80
|
+
end
|
81
|
+
|
82
|
+
def default_params
|
83
|
+
{'ids' => @profile.table_id,
|
84
|
+
'start-date' => format_time(@start_date),
|
85
|
+
'end-date' => format_time(@end_date)}
|
86
|
+
end
|
87
|
+
|
88
|
+
def segment_params
|
89
|
+
segment.nil? ? {} : {'segment' => segment}
|
90
|
+
end
|
91
|
+
|
92
|
+
def params
|
93
|
+
[
|
94
|
+
metrics.to_params,
|
95
|
+
dimensions.to_params,
|
96
|
+
sort.to_params,
|
97
|
+
filters.to_params,
|
98
|
+
page_params,
|
99
|
+
segment_params
|
100
|
+
].inject(default_params) do |p, i|
|
101
|
+
p.merge(i)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def format_time(t)
|
106
|
+
t.strftime('%Y-%m-%d')
|
107
|
+
end
|
108
|
+
|
109
|
+
def send_request_for_body
|
110
|
+
request = DataRequest.new(@profile.session, URL, params)
|
111
|
+
response = request.send_request
|
112
|
+
response.body
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Garb
|
2
|
+
class ResultSet
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
attr_accessor :total_results, :sampled
|
6
|
+
|
7
|
+
alias :sampled? :sampled
|
8
|
+
|
9
|
+
def initialize(results)
|
10
|
+
@results = results
|
11
|
+
end
|
12
|
+
|
13
|
+
def each(&block)
|
14
|
+
@results.each(&block)
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_a
|
18
|
+
@results
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/garb/session.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
module Garb
|
2
|
+
class Session
|
3
|
+
module Methods
|
4
|
+
attr_accessor :auth_token, :access_token, :email
|
5
|
+
|
6
|
+
# use only for single user authentication
|
7
|
+
def login(email, password, opts={})
|
8
|
+
self.email = email
|
9
|
+
auth_request = AuthenticationRequest.new(email, password, opts)
|
10
|
+
self.auth_token = auth_request.auth_token(opts)
|
11
|
+
end
|
12
|
+
|
13
|
+
def single_user?
|
14
|
+
auth_token && auth_token.is_a?(String)
|
15
|
+
end
|
16
|
+
|
17
|
+
def oauth_user?
|
18
|
+
!access_token.nil?
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
include Methods
|
23
|
+
extend Methods
|
24
|
+
end
|
25
|
+
end
|
data/lib/garb/step.rb
ADDED
data/lib/garb/version.rb
ADDED
data/lib/garb.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'net/https'
|
3
|
+
|
4
|
+
require 'cgi'
|
5
|
+
require 'ostruct'
|
6
|
+
require 'crack'
|
7
|
+
|
8
|
+
begin
|
9
|
+
require 'active_support/inflector'
|
10
|
+
require 'active_support/deprecation'
|
11
|
+
rescue Exception => e
|
12
|
+
require 'active_support'
|
13
|
+
end
|
14
|
+
|
15
|
+
require 'garb/version'
|
16
|
+
require 'garb/authentication_request'
|
17
|
+
require 'garb/data_request'
|
18
|
+
require 'garb/account_feed_request'
|
19
|
+
require 'garb/session'
|
20
|
+
require 'garb/profile_reports'
|
21
|
+
require 'garb/step'
|
22
|
+
require 'garb/destination'
|
23
|
+
require 'garb/goal'
|
24
|
+
require 'garb/profile'
|
25
|
+
require 'garb/account'
|
26
|
+
require 'garb/filter_parameters'
|
27
|
+
require 'garb/report_parameter'
|
28
|
+
require 'garb/result_set'
|
29
|
+
require 'garb/report_response'
|
30
|
+
require 'garb/resource'
|
31
|
+
require 'garb/report'
|
32
|
+
|
33
|
+
require 'garb/model'
|
34
|
+
|
35
|
+
# management
|
36
|
+
require 'garb/management/feed'
|
37
|
+
require 'garb/management/segment'
|
38
|
+
require 'garb/management/account'
|
39
|
+
require 'garb/management/web_property'
|
40
|
+
require 'garb/management/profile'
|
41
|
+
require 'garb/management/goal'
|
42
|
+
|
43
|
+
require 'support'
|
44
|
+
|
45
|
+
module Garb
|
46
|
+
GA = "http://schemas.google.com/analytics/2008"
|
47
|
+
|
48
|
+
extend self
|
49
|
+
|
50
|
+
def to_google_analytics(thing)
|
51
|
+
return thing.to_google_analytics if thing.respond_to?(:to_google_analytics)
|
52
|
+
|
53
|
+
"ga:#{thing.to_s.camelize(:lower)}"
|
54
|
+
end
|
55
|
+
alias :to_ga :to_google_analytics
|
56
|
+
|
57
|
+
def from_google_analytics(thing)
|
58
|
+
thing.to_s.gsub(/^ga\:/, '').underscore
|
59
|
+
end
|
60
|
+
alias :from_ga :from_google_analytics
|
61
|
+
|
62
|
+
def parse_properties(entry)
|
63
|
+
Hash[entry['dxp:property'].map {|p| [Garb.from_ga(p['name']),p['value']]}]
|
64
|
+
end
|
65
|
+
|
66
|
+
def parse_link(entry, rel)
|
67
|
+
entry['link'].detect {|link| link["rel"] == rel}['href']
|
68
|
+
end
|
69
|
+
end
|
data/lib/support.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
class SymbolOperator
|
2
|
+
def initialize(field, operator)
|
3
|
+
@field, @operator = field, operator
|
4
|
+
end unless method_defined?(:initialize)
|
5
|
+
|
6
|
+
def to_google_analytics
|
7
|
+
operators = {
|
8
|
+
:eql => '==',
|
9
|
+
:not_eql => '!=',
|
10
|
+
:gt => '>',
|
11
|
+
:gte => '>=',
|
12
|
+
:lt => '<',
|
13
|
+
:lte => '<=',
|
14
|
+
:matches => '==',
|
15
|
+
:does_not_match => '!=',
|
16
|
+
:contains => '=~',
|
17
|
+
:does_not_contain => '!~',
|
18
|
+
:substring => '=@',
|
19
|
+
:not_substring => '!@',
|
20
|
+
:desc => '-',
|
21
|
+
:descending => '-'
|
22
|
+
}
|
23
|
+
|
24
|
+
target = Garb.to_google_analytics(@field)
|
25
|
+
operator = operators[@operator]
|
26
|
+
|
27
|
+
[:desc, :descending].include?(@operator) ? "#{operator}#{target}" : "#{target}#{operator}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class Symbol
|
32
|
+
[:eql, :not_eql, :gt, :gte, :lt, :lte, :desc, :descending,
|
33
|
+
:matches, :does_not_match, :contains, :does_not_contain,
|
34
|
+
:substring, :not_substring].each do |operator|
|
35
|
+
|
36
|
+
define_method(operator) do
|
37
|
+
SymbolOperator.new(self, operator)
|
38
|
+
end unless method_defined?(operator)
|
39
|
+
end
|
40
|
+
end
|