legato 0.0.10 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +44 -5
- data/lib/legato/model.rb +12 -0
- data/lib/legato/query.rb +25 -7
- data/lib/legato/version.rb +1 -1
- data/spec/lib/legato/model_spec.rb +27 -0
- data/spec/lib/legato/query_spec.rb +8 -0
- metadata +2 -2
data/README.md
CHANGED
@@ -68,19 +68,19 @@ Here's what google has to say: http://code.google.com/apis/analytics/docs/gdata/
|
|
68
68
|
|
69
69
|
Return entries with exits counts greater than or equal to 2000
|
70
70
|
|
71
|
-
filter :high_exits, lambda {gte(:exits, 2000)}
|
71
|
+
filter :high_exits, &lambda {gte(:exits, 2000)}
|
72
72
|
|
73
73
|
Return entries with pageview metric less than or equal to 200
|
74
74
|
|
75
|
-
filter :low_pageviews, lambda {lte(:pageviews, 200)}
|
75
|
+
filter :low_pageviews, &lambda {lte(:pageviews, 200)}
|
76
76
|
|
77
77
|
Filters with dimensions
|
78
78
|
|
79
|
-
filter :for_browser, lambda {|browser| matches(:
|
79
|
+
filter :for_browser, &lambda {|browser| matches(:browser, browser)}
|
80
80
|
|
81
81
|
Filters with OR
|
82
82
|
|
83
|
-
filter :browsers, lambda {|*browsers| browsers.map {|browser| matches(:
|
83
|
+
filter :browsers, &lambda {|*browsers| browsers.map {|browser| matches(:browser, browser)}}
|
84
84
|
|
85
85
|
|
86
86
|
## Using and Chaining Filters ##
|
@@ -109,7 +109,7 @@ Be sure to pass the appropriate number of arguments matching the lambda for your
|
|
109
109
|
|
110
110
|
For a filter defined like this:
|
111
111
|
|
112
|
-
filter :browsers, lambda {|*browsers| browsers.map {|browser| matches(:
|
112
|
+
filter :browsers, &lambda {|*browsers| browsers.map {|browser| matches(:browser, browser)}}
|
113
113
|
|
114
114
|
We can use it like this, passing any number of arguments:
|
115
115
|
|
@@ -140,6 +140,45 @@ Operators on dimensions:
|
|
140
140
|
substring => '=@',
|
141
141
|
not_substring => '!@'
|
142
142
|
|
143
|
+
## Dynamic Segment
|
144
|
+
|
145
|
+
Your query can have a dynamic segment, which works with filter expressions. It
|
146
|
+
works like an [advanced
|
147
|
+
segment](https://support.google.com/analytics/answer/1033017?hl=en), except you
|
148
|
+
don't have to create it beforehand, you can just specify it at query time.
|
149
|
+
|
150
|
+
Some of the numbers you'll get will be different from using a filter, since
|
151
|
+
[the subset of visits matched happens before dimensions and metrics are
|
152
|
+
calculated](http://ga-dev-tools.appspot.com/explorer/) (hover on the `segment`
|
153
|
+
parameter to see).
|
154
|
+
|
155
|
+
Some metrics and dimensions are not allowed for segments, see the [API
|
156
|
+
documentation](https://developers.google.com/analytics/devguides/reporting/core/v3/reference#segment)
|
157
|
+
for more details.
|
158
|
+
|
159
|
+
### Defining, using and chaining filters
|
160
|
+
|
161
|
+
Return entries with exits counts greater than or equal to 2000
|
162
|
+
|
163
|
+
segment :high_exits do
|
164
|
+
gte(:exits, 2000)
|
165
|
+
end
|
166
|
+
|
167
|
+
Return entries with pageview metric less than or equal to 200
|
168
|
+
|
169
|
+
segment :low_pageviews do
|
170
|
+
lte(:pageviews, 200)
|
171
|
+
end
|
172
|
+
|
173
|
+
You can chain them
|
174
|
+
|
175
|
+
Exit.high_exits.low_pageviews(profile)
|
176
|
+
|
177
|
+
and call them directly on the profile
|
178
|
+
|
179
|
+
profile.exit.high_exits.low_pageviews
|
180
|
+
|
181
|
+
|
143
182
|
## Accounts, WebProperties, Profiles, and Goals ##
|
144
183
|
|
145
184
|
> Legato::Management::Account.all(user)
|
data/lib/legato/model.rb
CHANGED
@@ -26,6 +26,18 @@ module Legato
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
+
def segments
|
30
|
+
@segments ||= {}
|
31
|
+
end
|
32
|
+
|
33
|
+
def segment(name, &block)
|
34
|
+
segments[name] = block
|
35
|
+
|
36
|
+
(class << self; self; end).instance_eval do
|
37
|
+
define_method(name) {|*args| Query.new(self).apply_segment_filter(*args, &block)}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
29
41
|
def set_instance_klass(klass)
|
30
42
|
@instance_klass = klass
|
31
43
|
end
|
data/lib/legato/query.rb
CHANGED
@@ -11,6 +11,12 @@ module Legato
|
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
+
def define_segment_filter(name, &block)
|
15
|
+
(class << self; self; end).instance_eval do
|
16
|
+
define_method(name) {|*args| apply_segment_filter(*args, &block)}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
14
20
|
def self.define_filter_operators(*methods)
|
15
21
|
methods.each do |method|
|
16
22
|
class_eval <<-CODE
|
@@ -24,12 +30,13 @@ module Legato
|
|
24
30
|
attr_reader :parent_klass
|
25
31
|
attr_accessor :profile, :start_date, :end_date
|
26
32
|
attr_accessor :sort, :limit, :offset, :quota_user #, :segment # individual, overwritten
|
27
|
-
attr_accessor :filters #
|
33
|
+
attr_accessor :filters, :segment_filters # combined, can be appended to
|
28
34
|
|
29
35
|
def initialize(klass)
|
30
36
|
@loaded = false
|
31
37
|
@parent_klass = klass
|
32
38
|
self.filters = FilterSet.new
|
39
|
+
self.segment_filters = FilterSet.new
|
33
40
|
self.start_date = Time.now - MONTH
|
34
41
|
self.end_date = Time.now
|
35
42
|
|
@@ -37,10 +44,9 @@ module Legato
|
|
37
44
|
define_filter(name, &block)
|
38
45
|
end
|
39
46
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
# end
|
47
|
+
klass.segments.each do |name, block|
|
48
|
+
define_segment_filter(name, &block)
|
49
|
+
end
|
44
50
|
end
|
45
51
|
|
46
52
|
def instance_klass
|
@@ -48,6 +54,14 @@ module Legato
|
|
48
54
|
end
|
49
55
|
|
50
56
|
def apply_filter(*args, &block)
|
57
|
+
apply_filter_expression(self.filters, *args, &block)
|
58
|
+
end
|
59
|
+
|
60
|
+
def apply_segment_filter(*args, &block)
|
61
|
+
apply_filter_expression(self.segment_filters, *args, &block)
|
62
|
+
end
|
63
|
+
|
64
|
+
def apply_filter_expression(filter_set, *args, &block)
|
51
65
|
@profile = extract_profile(args)
|
52
66
|
|
53
67
|
join_character = Legato.and_join_character # filters are joined by AND
|
@@ -55,7 +69,7 @@ module Legato
|
|
55
69
|
# # block returns one filter or an array of filters
|
56
70
|
Array.wrap(instance_exec(*args, &block)).each do |filter|
|
57
71
|
filter.join_character ||= join_character # only set when not set explicitly
|
58
|
-
|
72
|
+
filter_set << filter
|
59
73
|
|
60
74
|
join_character = Legato.or_join_character # arrays are joined by OR
|
61
75
|
end
|
@@ -169,6 +183,10 @@ module Legato
|
|
169
183
|
@sort = Legato::ListParameter.new(:sort, arr)
|
170
184
|
end
|
171
185
|
|
186
|
+
def segment
|
187
|
+
"dynamic::#{segment_filters.to_params}" if segment_filters.any?
|
188
|
+
end
|
189
|
+
|
172
190
|
# def segment_id
|
173
191
|
# segment.nil? ? nil : "gaid::#{segment}"
|
174
192
|
# end
|
@@ -184,7 +202,7 @@ module Legato
|
|
184
202
|
'end-date' => Legato.format_time(end_date),
|
185
203
|
'max-results' => limit,
|
186
204
|
'start-index' => offset,
|
187
|
-
|
205
|
+
'segment' => segment,
|
188
206
|
'filters' => filters.to_params, # defaults to AND filtering
|
189
207
|
'fields' => REQUEST_FIELDS,
|
190
208
|
'quotaUser' => quota_user
|
data/lib/legato/version.rb
CHANGED
@@ -69,6 +69,33 @@ describe "Legato::Model" do
|
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
|
+
context "with segments" do
|
73
|
+
before :each do
|
74
|
+
@block = lambda {}
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'creates a class method' do
|
78
|
+
@model.segment :high, &@block
|
79
|
+
@model.respond_to?(:high).should be_true
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'stores the segment' do
|
83
|
+
@model.segment :high, &@block
|
84
|
+
@model.segments[:high].should == @block
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'returns a Query instance for a segment' do
|
88
|
+
query = stub(:apply_segment_filter => "a query")
|
89
|
+
Legato::Query.stubs(:new).returns(query)
|
90
|
+
|
91
|
+
@model.segment :high, &@block
|
92
|
+
@model.high('arg1').should == 'a query'
|
93
|
+
|
94
|
+
Legato::Query.should have_received(:new).with(@model)
|
95
|
+
query.should have_received(:apply_segment_filter).with('arg1')
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
72
99
|
# xit 'has an instance klass'
|
73
100
|
# xit 'sets an instance klass'
|
74
101
|
|
@@ -20,6 +20,7 @@ describe Legato::Query do
|
|
20
20
|
@klass = Class.new
|
21
21
|
@block = lambda {eql(:key, 1000)}
|
22
22
|
@klass.stubs(:filters).returns({:high => @block})
|
23
|
+
@klass.stubs(:segments).returns([])
|
23
24
|
|
24
25
|
@query = Legato::Query.new(@klass)
|
25
26
|
end
|
@@ -354,6 +355,13 @@ describe Legato::Query do
|
|
354
355
|
@query.to_params['filters'].should == 'filter set parameters'
|
355
356
|
end
|
356
357
|
|
358
|
+
it 'includes the dynamic segment' do
|
359
|
+
segment_filters = stub(:to_params => 'segment parameter', :any? => true)
|
360
|
+
@query.stubs(:segment_filters).returns(segment_filters)
|
361
|
+
|
362
|
+
@query.to_params['segment'].should == 'dynamic::segment parameter'
|
363
|
+
end
|
364
|
+
|
357
365
|
it 'includes metrics' do
|
358
366
|
metrics = Legato::ListParameter.new(:metrics)
|
359
367
|
metrics.stubs(:to_params).returns({'metrics' => 'pageviews,exits'})
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: legato
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-07-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|