legato 0.0.10 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|