mixpanel-ruby 2.2.0 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|