mixpanel-ruby 2.2.0 → 2.3.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.
- checksums.yaml +5 -5
- data/.travis.yml +3 -7
- data/Readme.rdoc +6 -0
- data/lib/mixpanel-ruby/consumer.rb +16 -4
- data/lib/mixpanel-ruby/events.rb +2 -2
- data/lib/mixpanel-ruby/groups.rb +201 -0
- data/lib/mixpanel-ruby/people.rb +1 -1
- data/lib/mixpanel-ruby/tracker.rb +12 -1
- data/lib/mixpanel-ruby/version.rb +1 -1
- data/spec/mixpanel-ruby/consumer_spec.rb +46 -1
- data/spec/mixpanel-ruby/groups_spec.rb +159 -0
- metadata +8 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 0a4bc0206903c9c7d7e61253d7cfe248e17f698a754dac067e3d6997ee44688a
|
|
4
|
+
data.tar.gz: eda4910784b73583c7ff29fcbeaae86b1259e407d8cddf5c5c9ccb7ad9004661
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ba267b81907f663ef400b694973569c2e2e00c323e8e199bea82516d3552c73f2ffcc6c864c0fca2123f53a3e246218e60c64e58b51aab5ac96792dae8f76a13
|
|
7
|
+
data.tar.gz: 541c0b8b4da498f37a749d76542fad417c776c83f4d583c8ae5bbbfbba9979103cfb634bb4a3d8ae6748b6b302ca546524edc80258423eb2e862d279328d07f1
|
data/.travis.yml
CHANGED
data/Readme.rdoc
CHANGED
|
@@ -49,6 +49,12 @@ In particular, for Rails apps, the following projects are currently actively mai
|
|
|
49
49
|
|
|
50
50
|
== Changes
|
|
51
51
|
|
|
52
|
+
== 2.2.2
|
|
53
|
+
* Add Group Analytics support with Mixpanel::Groups
|
|
54
|
+
|
|
55
|
+
== 2.2.1
|
|
56
|
+
* Fix buffer clearing on partially successful writes in BufferedConsumer.
|
|
57
|
+
|
|
52
58
|
== 2.2.0
|
|
53
59
|
* Add Mixpanel::ErrorHandler to simplify custom error handling.
|
|
54
60
|
* Modify Mixpanel::People#fix_property_dates to handle ActiveSupport::TimeWithZone.
|
|
@@ -58,9 +58,13 @@ module Mixpanel
|
|
|
58
58
|
# they will be used instead of the default Mixpanel endpoints.
|
|
59
59
|
# This can be useful for proxying, debugging, or if you prefer
|
|
60
60
|
# not to use SSL for your events.
|
|
61
|
-
def initialize(events_endpoint=nil,
|
|
61
|
+
def initialize(events_endpoint=nil,
|
|
62
|
+
update_endpoint=nil,
|
|
63
|
+
groups_endpoint=nil,
|
|
64
|
+
import_endpoint=nil)
|
|
62
65
|
@events_endpoint = events_endpoint || 'https://api.mixpanel.com/track'
|
|
63
66
|
@update_endpoint = update_endpoint || 'https://api.mixpanel.com/engage'
|
|
67
|
+
@groups_endpoint = groups_endpoint || 'https://api.mixpanel.com/groups'
|
|
64
68
|
@import_endpoint = import_endpoint || 'https://api.mixpanel.com/import'
|
|
65
69
|
end
|
|
66
70
|
|
|
@@ -75,6 +79,7 @@ module Mixpanel
|
|
|
75
79
|
endpoint = {
|
|
76
80
|
:event => @events_endpoint,
|
|
77
81
|
:profile_update => @update_endpoint,
|
|
82
|
+
:group_update => @groups_endpoint,
|
|
78
83
|
:import => @import_endpoint,
|
|
79
84
|
}[type]
|
|
80
85
|
|
|
@@ -225,9 +230,16 @@ module Mixpanel
|
|
|
225
230
|
private
|
|
226
231
|
|
|
227
232
|
def flush_type(type)
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
@
|
|
233
|
+
sent_messages = 0
|
|
234
|
+
begin
|
|
235
|
+
@buffers[type].each_slice(@max_length) do |chunk|
|
|
236
|
+
data = chunk.map {|message| JSON.load(message)['data'] }
|
|
237
|
+
@sink.call(type, {'data' => data}.to_json)
|
|
238
|
+
sent_messages += chunk.length
|
|
239
|
+
end
|
|
240
|
+
rescue
|
|
241
|
+
@buffers[type].slice!(0, sent_messages)
|
|
242
|
+
raise
|
|
231
243
|
end
|
|
232
244
|
@buffers[type] = []
|
|
233
245
|
end
|
data/lib/mixpanel-ruby/events.rb
CHANGED
|
@@ -55,7 +55,7 @@ module Mixpanel
|
|
|
55
55
|
properties = {
|
|
56
56
|
'distinct_id' => distinct_id,
|
|
57
57
|
'token' => @token,
|
|
58
|
-
'time' => Time.now.
|
|
58
|
+
'time' => Time.now.to_f,
|
|
59
59
|
'mp_lib' => 'ruby',
|
|
60
60
|
'$lib_version' => Mixpanel::VERSION,
|
|
61
61
|
}.merge(properties)
|
|
@@ -103,7 +103,7 @@ module Mixpanel
|
|
|
103
103
|
properties = {
|
|
104
104
|
'distinct_id' => distinct_id,
|
|
105
105
|
'token' => @token,
|
|
106
|
-
'time' => Time.now.
|
|
106
|
+
'time' => Time.now.to_f,
|
|
107
107
|
'mp_lib' => 'ruby',
|
|
108
108
|
'$lib_version' => Mixpanel::VERSION,
|
|
109
109
|
}.merge(properties)
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
require 'date'
|
|
2
|
+
require 'json'
|
|
3
|
+
require 'time'
|
|
4
|
+
|
|
5
|
+
require 'mixpanel-ruby/consumer'
|
|
6
|
+
require 'mixpanel-ruby/error'
|
|
7
|
+
|
|
8
|
+
module Mixpanel
|
|
9
|
+
|
|
10
|
+
# Handles formatting Mixpanel group updates and
|
|
11
|
+
# sending them to the consumer. You will rarely need
|
|
12
|
+
# to instantiate this class directly- to send
|
|
13
|
+
# group updates, use Mixpanel::Tracker#groups
|
|
14
|
+
#
|
|
15
|
+
# tracker = Mixpanel::Tracker.new(YOUR_MIXPANEL_TOKEN)
|
|
16
|
+
# tracker.groups.set(...) or .set_once(..), or .delete(...) etc.
|
|
17
|
+
class Groups
|
|
18
|
+
|
|
19
|
+
# You likely won't need to instantiate instances of Mixpanel::Groups
|
|
20
|
+
# directly. The best way to get an instance of Mixpanel::Groups is
|
|
21
|
+
#
|
|
22
|
+
# tracker = Mixpanel::Tracker.new(YOUR_MIXPANEL_TOKEN)
|
|
23
|
+
# tracker.groups # An instance of Mixpanel::Groups
|
|
24
|
+
#
|
|
25
|
+
def initialize(token, error_handler=nil, &block)
|
|
26
|
+
@token = token
|
|
27
|
+
@error_handler = error_handler || ErrorHandler.new
|
|
28
|
+
|
|
29
|
+
if block
|
|
30
|
+
@sink = block
|
|
31
|
+
else
|
|
32
|
+
consumer = Consumer.new
|
|
33
|
+
@sink = consumer.method(:send!)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Sets properties on a group record. Takes a Hash with string
|
|
38
|
+
# keys, and values that are strings, numbers, booleans, or
|
|
39
|
+
# DateTimes
|
|
40
|
+
#
|
|
41
|
+
# tracker = Mixpanel::Tracker.new(YOUR_MIXPANEL_TOKEN)
|
|
42
|
+
# # Sets properties on group with id "1234"
|
|
43
|
+
# tracker.groups.set("GROUP KEY", "1234", {
|
|
44
|
+
# 'company' => 'Acme',
|
|
45
|
+
# 'plan' => 'Premium',
|
|
46
|
+
# 'Sign-Up Date' => DateTime.now
|
|
47
|
+
# });
|
|
48
|
+
#
|
|
49
|
+
# If you provide an ip argument, \Mixpanel will use that
|
|
50
|
+
# ip address for geolocation (rather than the ip of your server)
|
|
51
|
+
def set(group_key, group_id, properties, ip=nil, optional_params={})
|
|
52
|
+
properties = fix_property_dates(properties)
|
|
53
|
+
message = {
|
|
54
|
+
'$group_key' => group_key,
|
|
55
|
+
'$group_id' => group_id,
|
|
56
|
+
'$set' => properties,
|
|
57
|
+
}.merge(optional_params)
|
|
58
|
+
message['$ip'] = ip if ip
|
|
59
|
+
|
|
60
|
+
update(message)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# set_once works just like #set, but will only change the
|
|
64
|
+
# value of properties if they are not already present
|
|
65
|
+
# in the group. That means you can call set_once many times
|
|
66
|
+
# without changing an original value.
|
|
67
|
+
#
|
|
68
|
+
# tracker = Mixpanel::Tracker.new(YOUR_MIXPANEL_TOKEN)
|
|
69
|
+
# tracker.groups.set_once("GROUP KEY", "1234", {
|
|
70
|
+
# 'First Login Date': DateTime.now
|
|
71
|
+
# });
|
|
72
|
+
#
|
|
73
|
+
def set_once(group_key, group_id, properties, ip=nil, optional_params={})
|
|
74
|
+
properties = fix_property_dates(properties)
|
|
75
|
+
message = {
|
|
76
|
+
'$group_key' => group_key,
|
|
77
|
+
'$group_id' => group_id,
|
|
78
|
+
'$set_once' => properties,
|
|
79
|
+
}.merge(optional_params)
|
|
80
|
+
message['$ip'] = ip if ip
|
|
81
|
+
|
|
82
|
+
update(message)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Removes a specific value in a list property
|
|
86
|
+
#
|
|
87
|
+
# tracker = Mixpanel::Tracker.new(YOUR_MIXPANEL_TOKEN)
|
|
88
|
+
#
|
|
89
|
+
# # removes "socks" from the "Items purchased" list property
|
|
90
|
+
# # for the specified group
|
|
91
|
+
# tracker.groups.remove("GROUP KEY", "1234", { 'Items purchased' => 'socks' })
|
|
92
|
+
#
|
|
93
|
+
def remove(group_key, group_id, properties, ip=nil, optional_params={})
|
|
94
|
+
properties = fix_property_dates(properties)
|
|
95
|
+
message = {
|
|
96
|
+
'$group_key' => group_key,
|
|
97
|
+
'$group_id' => group_id,
|
|
98
|
+
'$remove' => properties,
|
|
99
|
+
}.merge(optional_params)
|
|
100
|
+
message['$ip'] = ip if ip
|
|
101
|
+
|
|
102
|
+
update(message)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Set union on list valued properties.
|
|
106
|
+
# Associates a list containing all elements of a given list,
|
|
107
|
+
# and all elements currently in a list associated with the given
|
|
108
|
+
# property. After a union, every element in the list associated
|
|
109
|
+
# with a property will be unique.
|
|
110
|
+
#
|
|
111
|
+
# tracker = Mixpanel::Tracker.new(YOUR_MIXPANEL_TOKEN)
|
|
112
|
+
# tracker.groups.union("GROUP KEY", "1234", {
|
|
113
|
+
# 'Levels Completed' => ['Suffragette City']
|
|
114
|
+
# });
|
|
115
|
+
#
|
|
116
|
+
def union(group_key, group_id, properties, ip=nil, optional_params={})
|
|
117
|
+
properties = fix_property_dates(properties)
|
|
118
|
+
message = {
|
|
119
|
+
'$group_key' => group_key,
|
|
120
|
+
'$group_id' => group_id,
|
|
121
|
+
'$union' => properties,
|
|
122
|
+
}.merge(optional_params)
|
|
123
|
+
message['$ip'] = ip if ip
|
|
124
|
+
|
|
125
|
+
update(message)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Removes properties and their values from a group.
|
|
129
|
+
#
|
|
130
|
+
# tracker = Mixpanel::Tracker.new(YOUR_MIXPANEL_TOKEN)
|
|
131
|
+
#
|
|
132
|
+
# # removes a single property and its value from a group
|
|
133
|
+
# tracker.groups.unset("GROUP KEY", "1234", "Overdue Since")
|
|
134
|
+
#
|
|
135
|
+
# # removes multiple properties and their values from a group
|
|
136
|
+
# tracker.groups.unset("GROUP KEY",
|
|
137
|
+
# "1234",
|
|
138
|
+
# ["Overdue Since", "Paid Date"])
|
|
139
|
+
#
|
|
140
|
+
def unset(group_key, group_id, properties, ip=nil, optional_params={})
|
|
141
|
+
properties = [properties] unless properties.is_a?(Array)
|
|
142
|
+
message = {
|
|
143
|
+
'$group_key' => group_key,
|
|
144
|
+
'$group_id' => group_id,
|
|
145
|
+
'$unset' => properties,
|
|
146
|
+
}.merge(optional_params)
|
|
147
|
+
message['$ip'] = ip if ip
|
|
148
|
+
|
|
149
|
+
update(message)
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# Permanently delete a group from \Mixpanel groups analytics (all group
|
|
153
|
+
# properties on events stay)
|
|
154
|
+
def delete_group(group_key, group_id, optional_params={})
|
|
155
|
+
update({
|
|
156
|
+
'$group_key' => group_key,
|
|
157
|
+
'$group_id' => group_id,
|
|
158
|
+
'$delete' => '',
|
|
159
|
+
}.merge(optional_params))
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Send a generic update to \Mixpanel groups analytics.
|
|
163
|
+
# Caller is responsible for formatting the update message, as
|
|
164
|
+
# documented in the \Mixpanel HTTP specification, and passing
|
|
165
|
+
# the message as a dict to #update. This
|
|
166
|
+
# method might be useful if you want to use very new
|
|
167
|
+
# or experimental features of groups analytics from Ruby
|
|
168
|
+
# The \Mixpanel HTTP tracking API is documented at
|
|
169
|
+
# https://mixpanel.com/help/reference/http
|
|
170
|
+
def update(message)
|
|
171
|
+
data = {
|
|
172
|
+
'$token' => @token,
|
|
173
|
+
'$time' => Time.now.to_f,
|
|
174
|
+
}.merge(message)
|
|
175
|
+
|
|
176
|
+
message = {'data' => data}
|
|
177
|
+
|
|
178
|
+
ret = true
|
|
179
|
+
begin
|
|
180
|
+
@sink.call(:group_update, message.to_json)
|
|
181
|
+
rescue MixpanelError => e
|
|
182
|
+
@error_handler.handle(e)
|
|
183
|
+
ret = false
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
ret
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
private
|
|
190
|
+
|
|
191
|
+
def fix_property_dates(properties)
|
|
192
|
+
properties.inject({}) do |ret, (key, value)|
|
|
193
|
+
value = value.respond_to?(:new_offset) ? value.new_offset('0') : value
|
|
194
|
+
value = value.respond_to?(:utc) ? value.utc : value # Handle ActiveSupport::TimeWithZone
|
|
195
|
+
|
|
196
|
+
ret[key] = value.respond_to?(:strftime) ? value.strftime('%Y-%m-%dT%H:%M:%S') : value
|
|
197
|
+
ret
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
end
|
data/lib/mixpanel-ruby/people.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
require 'mixpanel-ruby/events.rb'
|
|
2
2
|
require 'mixpanel-ruby/people.rb'
|
|
3
|
+
require 'mixpanel-ruby/groups.rb'
|
|
3
4
|
|
|
4
5
|
module Mixpanel
|
|
5
6
|
# Use Mixpanel::Tracker to track events and profile updates in your application.
|
|
@@ -13,16 +14,25 @@ module Mixpanel
|
|
|
13
14
|
# tracker = Mixpanel::Tracker.new(YOUR_MIXPANEL_TOKEN)
|
|
14
15
|
# tracker.people.set(a_distinct_id, {properties})
|
|
15
16
|
#
|
|
17
|
+
# To send groups updates, call
|
|
18
|
+
#
|
|
19
|
+
# tracker = Mixpanel::Tracker.new(YOUR_MIXPANEL_TOKEN)
|
|
20
|
+
# tracker.groups.set(group_key, group_id, {properties})
|
|
21
|
+
#
|
|
16
22
|
# You can find your project token in the settings dialog for your
|
|
17
23
|
# project, inside of the Mixpanel web application.
|
|
18
24
|
#
|
|
19
25
|
# Mixpanel::Tracker is a subclass of Mixpanel::Events, and exposes
|
|
20
26
|
# an instance of Mixpanel::People as Tracker#people
|
|
27
|
+
# and an instance of Mixpanel::Groups as Tracker#groups
|
|
21
28
|
class Tracker < Events
|
|
22
29
|
# An instance of Mixpanel::People. Use this to
|
|
23
30
|
# send profile updates
|
|
24
31
|
attr_reader :people
|
|
25
32
|
|
|
33
|
+
# An instance of Mixpanel::Groups. Use this to send groups updates
|
|
34
|
+
attr_reader :groups
|
|
35
|
+
|
|
26
36
|
# Takes your Mixpanel project token, as a string.
|
|
27
37
|
#
|
|
28
38
|
# tracker = Mixpanel::Tracker.new(YOUR_MIXPANEL_TOKEN)
|
|
@@ -46,6 +56,7 @@ module Mixpanel
|
|
|
46
56
|
super(token, error_handler, &block)
|
|
47
57
|
@token = token
|
|
48
58
|
@people = People.new(token, error_handler, &block)
|
|
59
|
+
@groups = Groups.new(token, error_handler, &block)
|
|
49
60
|
end
|
|
50
61
|
|
|
51
62
|
# A call to #track is a report that an event has occurred. #track
|
|
@@ -154,7 +165,7 @@ module Mixpanel
|
|
|
154
165
|
properties = {
|
|
155
166
|
'distinct_id' => distinct_id,
|
|
156
167
|
'token' => @token,
|
|
157
|
-
'time' => Time.now.
|
|
168
|
+
'time' => Time.now.to_f,
|
|
158
169
|
'mp_lib' => 'ruby',
|
|
159
170
|
'$lib_version' => Mixpanel::VERSION,
|
|
160
171
|
}.merge(properties)
|
|
@@ -22,6 +22,13 @@ describe Mixpanel::Consumer do
|
|
|
22
22
|
with(:body => {'data' => 'IlRFU1QgRVZFTlQgTUVTU0FHRSI=', 'verbose' => '1' })
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
+
it 'should send a request to api.mixpanel.com/groups on groups updates' do
|
|
26
|
+
stub_request(:any, 'https://api.mixpanel.com/groups').to_return({:body => '{"status": 1, "error": null}'})
|
|
27
|
+
subject.send!(:group_update, {'data' => 'TEST EVENT MESSAGE'}.to_json)
|
|
28
|
+
expect(WebMock).to have_requested(:post, 'https://api.mixpanel.com/groups').
|
|
29
|
+
with(:body => {'data' => 'IlRFU1QgRVZFTlQgTUVTU0FHRSI=', 'verbose' => '1' })
|
|
30
|
+
end
|
|
31
|
+
|
|
25
32
|
it 'should send a request to api.mixpanel.com/import on event imports' do
|
|
26
33
|
stub_request(:any, 'https://api.mixpanel.com/import').to_return({:body => '{"status": 1, "error": null}'})
|
|
27
34
|
subject.send!(:import, {'data' => 'TEST EVENT MESSAGE', 'api_key' => 'API_KEY','verbose' => '1' }.to_json)
|
|
@@ -55,7 +62,7 @@ describe Mixpanel::Consumer do
|
|
|
55
62
|
with(:body => {'data' => 'IlRFU1QgRVZFTlQgTUVTU0FHRSI=', 'verbose' => '1' })
|
|
56
63
|
end
|
|
57
64
|
|
|
58
|
-
it 'should raise server error when verbose is disabled' do
|
|
65
|
+
it 'should raise server error when verbose is disabled', :skip => true do
|
|
59
66
|
stub_request(:any, 'https://api.mixpanel.com/track').to_return({:body => '0'})
|
|
60
67
|
expect { subject.send!(:event, {'data' => 'TEST EVENT MESSAGE'}.to_json) }.to raise_exception(Mixpanel::ServerError, /Could not interpret Mixpanel server response: '0'/)
|
|
61
68
|
expect(WebMock).to have_requested(:post, 'https://api.mixpanel.com/track').
|
|
@@ -160,4 +167,42 @@ describe Mixpanel::BufferedConsumer do
|
|
|
160
167
|
|
|
161
168
|
end
|
|
162
169
|
|
|
170
|
+
context 'with failing requests' do
|
|
171
|
+
let(:sent_messages) { [] }
|
|
172
|
+
let(:submission_queue) { [] }
|
|
173
|
+
subject do
|
|
174
|
+
Mixpanel::BufferedConsumer.new(nil, nil, nil, 2) do |type, message|
|
|
175
|
+
raise Mixpanel::ServerError if submission_queue.shift == :fail
|
|
176
|
+
sent_messages << [type, message]
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
it 'clears any slices that complete on flush' do
|
|
181
|
+
# construct a consumer that is backed up and has a multi-slice buffer
|
|
182
|
+
3.times { submission_queue << :fail }
|
|
183
|
+
4.times do |i|
|
|
184
|
+
begin
|
|
185
|
+
subject.send!(:event, {'data' => i}.to_json)
|
|
186
|
+
rescue Mixpanel::ServerError
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
expect(sent_messages).to match_array([])
|
|
190
|
+
|
|
191
|
+
submission_queue << :pass
|
|
192
|
+
submission_queue << :fail
|
|
193
|
+
|
|
194
|
+
expect { subject.flush }.to raise_error Mixpanel::ServerError
|
|
195
|
+
expect(sent_messages).to match_array([
|
|
196
|
+
[:event, '{"data":[0,1]}']
|
|
197
|
+
])
|
|
198
|
+
|
|
199
|
+
submission_queue << :pass
|
|
200
|
+
subject.flush
|
|
201
|
+
expect(sent_messages).to match_array([
|
|
202
|
+
[:event, '{"data":[0,1]}'],
|
|
203
|
+
[:event, '{"data":[2,3]}'],
|
|
204
|
+
])
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
163
208
|
end
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'active_support/time'
|
|
3
|
+
|
|
4
|
+
require 'mixpanel-ruby/groups'
|
|
5
|
+
|
|
6
|
+
describe Mixpanel::Groups do
|
|
7
|
+
before(:each) do
|
|
8
|
+
@time_now = Time.parse('Jun 6 1972, 16:23:04')
|
|
9
|
+
allow(Time).to receive(:now).and_return(@time_now)
|
|
10
|
+
|
|
11
|
+
@log = []
|
|
12
|
+
@groups = Mixpanel::Groups.new('TEST TOKEN') do |type, message|
|
|
13
|
+
@log << [type, JSON.load(message)]
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'should send a well formed groups/set message' do
|
|
18
|
+
@groups.set("TEST GROUP KEY", "TEST GROUP ID", {
|
|
19
|
+
'$groupname' => 'Mixpanel',
|
|
20
|
+
'$grouprevenue' => 200
|
|
21
|
+
})
|
|
22
|
+
expect(@log).to eq([[:group_update, 'data' => {
|
|
23
|
+
'$token' => 'TEST TOKEN',
|
|
24
|
+
'$group_key' => 'TEST GROUP KEY',
|
|
25
|
+
'$group_id' => 'TEST GROUP ID',
|
|
26
|
+
'$time' => @time_now.to_i * 1000,
|
|
27
|
+
'$set' => {
|
|
28
|
+
'$groupname' => 'Mixpanel',
|
|
29
|
+
'$grouprevenue' => 200
|
|
30
|
+
}
|
|
31
|
+
}]])
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it 'should properly cast dates' do
|
|
35
|
+
@groups.set("TEST GROUP KEY", "TEST GROUP ID", {
|
|
36
|
+
'created_at' => DateTime.new(2013, 1, 2, 3, 4, 5)
|
|
37
|
+
})
|
|
38
|
+
expect(@log).to eq([[:group_update, 'data' => {
|
|
39
|
+
'$token' => 'TEST TOKEN',
|
|
40
|
+
'$group_key' => 'TEST GROUP KEY',
|
|
41
|
+
'$group_id' => 'TEST GROUP ID',
|
|
42
|
+
'$time' => @time_now.to_i * 1000,
|
|
43
|
+
'$set' => {
|
|
44
|
+
'created_at' => '2013-01-02T03:04:05'
|
|
45
|
+
}
|
|
46
|
+
}]])
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it 'should convert offset datetimes to UTC' do
|
|
50
|
+
@groups.set("TEST GROUP KEY", "TEST GROUP ID", {
|
|
51
|
+
'created_at' => DateTime.new(2013, 1, 1, 18, 4, 5, '-8')
|
|
52
|
+
})
|
|
53
|
+
expect(@log).to eq([[:group_update, 'data' => {
|
|
54
|
+
'$token' => 'TEST TOKEN',
|
|
55
|
+
'$group_key' => 'TEST GROUP KEY',
|
|
56
|
+
'$group_id' => 'TEST GROUP ID',
|
|
57
|
+
'$time' => @time_now.to_i * 1000,
|
|
58
|
+
'$set' => {
|
|
59
|
+
'created_at' => '2013-01-02T02:04:05'
|
|
60
|
+
}
|
|
61
|
+
}]])
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it 'should convert offset ActiveSupport::TimeWithZone objects to UTC' do
|
|
65
|
+
Time.zone = 'Pacific Time (US & Canada)'
|
|
66
|
+
@groups.set("TEST GROUP KEY", "TEST GROUP ID", {
|
|
67
|
+
'created_at' => Time.zone.local(2013, 1, 1, 18, 4, 5)
|
|
68
|
+
})
|
|
69
|
+
expect(@log).to eq([[:group_update, 'data' => {
|
|
70
|
+
'$token' => 'TEST TOKEN',
|
|
71
|
+
'$group_key' => 'TEST GROUP KEY',
|
|
72
|
+
'$group_id' => 'TEST GROUP ID',
|
|
73
|
+
'$time' => @time_now.to_i * 1000,
|
|
74
|
+
'$set' => {
|
|
75
|
+
'created_at' => '2013-01-02T02:04:05'
|
|
76
|
+
}
|
|
77
|
+
}]])
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it 'should send a well formed groups/set_once message' do
|
|
81
|
+
@groups.set_once("TEST GROUP KEY", "TEST GROUP ID", {
|
|
82
|
+
'$groupname' => 'Mixpanel',
|
|
83
|
+
'$grouprevenue' => 200
|
|
84
|
+
})
|
|
85
|
+
expect(@log).to eq([[:group_update, 'data' => {
|
|
86
|
+
'$token' => 'TEST TOKEN',
|
|
87
|
+
'$group_key' => 'TEST GROUP KEY',
|
|
88
|
+
'$group_id' => 'TEST GROUP ID',
|
|
89
|
+
'$time' => @time_now.to_i * 1000,
|
|
90
|
+
'$set_once' => {
|
|
91
|
+
'$groupname' => 'Mixpanel',
|
|
92
|
+
'$grouprevenue' => 200
|
|
93
|
+
}
|
|
94
|
+
}]])
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
it 'should send a well formed groups/remove message' do
|
|
98
|
+
@groups.remove("TEST GROUP KEY", "TEST GROUP ID", {
|
|
99
|
+
'Albums' => 'Diamond Dogs'
|
|
100
|
+
})
|
|
101
|
+
expect(@log).to eq([[:group_update, 'data' => {
|
|
102
|
+
'$token' => 'TEST TOKEN',
|
|
103
|
+
'$group_key' => 'TEST GROUP KEY',
|
|
104
|
+
'$group_id' => 'TEST GROUP ID',
|
|
105
|
+
'$time' => @time_now.to_i * 1000,
|
|
106
|
+
'$remove' => {
|
|
107
|
+
'Albums' => 'Diamond Dogs'
|
|
108
|
+
}
|
|
109
|
+
}]])
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
it 'should send a well formed groups/union message' do
|
|
113
|
+
@groups.union("TEST GROUP KEY", "TEST GROUP ID", {
|
|
114
|
+
'Albums' => ['Diamond Dogs']
|
|
115
|
+
})
|
|
116
|
+
expect(@log).to eq([[:group_update, 'data' => {
|
|
117
|
+
'$token' => 'TEST TOKEN',
|
|
118
|
+
'$group_key' => 'TEST GROUP KEY',
|
|
119
|
+
'$group_id' => 'TEST GROUP ID',
|
|
120
|
+
'$time' => @time_now.to_i * 1000,
|
|
121
|
+
'$union' => {
|
|
122
|
+
'Albums' => ['Diamond Dogs']
|
|
123
|
+
}
|
|
124
|
+
}]])
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
it 'should send a well formed unset message' do
|
|
128
|
+
@groups.unset("TEST GROUP KEY", "TEST GROUP ID", 'Albums')
|
|
129
|
+
expect(@log).to eq([[:group_update, 'data' => {
|
|
130
|
+
'$token' => 'TEST TOKEN',
|
|
131
|
+
'$group_key' => 'TEST GROUP KEY',
|
|
132
|
+
'$group_id' => 'TEST GROUP ID',
|
|
133
|
+
'$time' => @time_now.to_i * 1000,
|
|
134
|
+
'$unset' => ['Albums']
|
|
135
|
+
}]])
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
it 'should send a well formed unset message with multiple properties' do
|
|
139
|
+
@groups.unset("TEST GROUP KEY", "TEST GROUP ID", ['Albums', 'Vinyls'])
|
|
140
|
+
expect(@log).to eq([[:group_update, 'data' => {
|
|
141
|
+
'$token' => 'TEST TOKEN',
|
|
142
|
+
'$group_key' => 'TEST GROUP KEY',
|
|
143
|
+
'$group_id' => 'TEST GROUP ID',
|
|
144
|
+
'$time' => @time_now.to_i * 1000,
|
|
145
|
+
'$unset' => ['Albums', 'Vinyls']
|
|
146
|
+
}]])
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
it 'should send a well formed groups/delete message' do
|
|
150
|
+
@groups.delete_group("TEST GROUP KEY", "TEST GROUP ID")
|
|
151
|
+
expect(@log).to eq([[:group_update, 'data' => {
|
|
152
|
+
'$token' => 'TEST TOKEN',
|
|
153
|
+
'$group_key' => 'TEST GROUP KEY',
|
|
154
|
+
'$group_id' => 'TEST GROUP ID',
|
|
155
|
+
'$time' => @time_now.to_i * 1000,
|
|
156
|
+
'$delete' => ''
|
|
157
|
+
}]])
|
|
158
|
+
end
|
|
159
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mixpanel-ruby
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Mixpanel
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2022-08-02 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activesupport
|
|
@@ -86,6 +86,7 @@ files:
|
|
|
86
86
|
- lib/mixpanel-ruby/consumer.rb
|
|
87
87
|
- lib/mixpanel-ruby/error.rb
|
|
88
88
|
- lib/mixpanel-ruby/events.rb
|
|
89
|
+
- lib/mixpanel-ruby/groups.rb
|
|
89
90
|
- lib/mixpanel-ruby/people.rb
|
|
90
91
|
- lib/mixpanel-ruby/tracker.rb
|
|
91
92
|
- lib/mixpanel-ruby/version.rb
|
|
@@ -93,6 +94,7 @@ files:
|
|
|
93
94
|
- spec/mixpanel-ruby/consumer_spec.rb
|
|
94
95
|
- spec/mixpanel-ruby/error_spec.rb
|
|
95
96
|
- spec/mixpanel-ruby/events_spec.rb
|
|
97
|
+
- spec/mixpanel-ruby/groups_spec.rb
|
|
96
98
|
- spec/mixpanel-ruby/people_spec.rb
|
|
97
99
|
- spec/mixpanel-ruby/tracker_spec.rb
|
|
98
100
|
- spec/spec_helper.rb
|
|
@@ -100,7 +102,7 @@ homepage: https://mixpanel.com/help/reference/ruby
|
|
|
100
102
|
licenses:
|
|
101
103
|
- Apache License 2.0
|
|
102
104
|
metadata: {}
|
|
103
|
-
post_install_message:
|
|
105
|
+
post_install_message:
|
|
104
106
|
rdoc_options: []
|
|
105
107
|
require_paths:
|
|
106
108
|
- lib
|
|
@@ -115,9 +117,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
115
117
|
- !ruby/object:Gem::Version
|
|
116
118
|
version: '0'
|
|
117
119
|
requirements: []
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
signing_key:
|
|
120
|
+
rubygems_version: 3.3.7
|
|
121
|
+
signing_key:
|
|
121
122
|
specification_version: 4
|
|
122
123
|
summary: Official Mixpanel tracking library for ruby
|
|
123
124
|
test_files: []
|