mixpanel-ruby 1.0.2 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Readme.rdoc +4 -0
- data/lib/mixpanel-ruby/consumer.rb +10 -3
- data/lib/mixpanel-ruby/version.rb +1 -1
- data/spec/mixpanel-ruby/consumer_spec.rb +21 -16
- data/spec/mixpanel-ruby/tracker_spec.rb +5 -5
- metadata +2 -2
data/Readme.rdoc
CHANGED
@@ -38,6 +38,10 @@ For more information please visit:
|
|
38
38
|
|
39
39
|
== Changes
|
40
40
|
|
41
|
+
== 1.1.0
|
42
|
+
* The default consumer now sends requests (and expects responses) in
|
43
|
+
verbose, JSON mode, which may improve error reporting.
|
44
|
+
|
41
45
|
=== 1.0.2
|
42
46
|
* Allow ip and optional_params arguments to be accepted by all
|
43
47
|
Mixpanel::People methods (except #destroy_user)
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'base64'
|
2
2
|
require 'net/https'
|
3
|
+
require 'json'
|
3
4
|
|
4
5
|
module Mixpanel
|
5
6
|
class ConnectionError < IOError
|
@@ -86,16 +87,22 @@ module Mixpanel
|
|
86
87
|
client.use_ssl = true
|
87
88
|
Mixpanel.with_http(client)
|
88
89
|
|
89
|
-
form_data = { "data" => data }
|
90
|
+
form_data = { "data" => data, "verbose" => 1 }
|
90
91
|
form_data.merge!("api_key" => api_key) if api_key
|
91
92
|
request = Net::HTTP::Post.new(uri.request_uri)
|
92
93
|
request.set_form_data(form_data)
|
93
94
|
response = client.request(request)
|
94
95
|
|
95
|
-
|
96
|
+
succeeded = false
|
97
|
+
if response.code == '200'
|
98
|
+
result = JSON.load(response.body) rescue {}
|
99
|
+
succeeded = result['status'] == 1
|
100
|
+
end
|
101
|
+
|
102
|
+
if succeeded
|
96
103
|
return true
|
97
104
|
else
|
98
|
-
raise ConnectionError.new(
|
105
|
+
raise ConnectionError.new("Could not write to Mixpanel, server responded with #{response.code} returning: '#{response.body}'")
|
99
106
|
end
|
100
107
|
end
|
101
108
|
end
|
@@ -10,31 +10,36 @@ describe Mixpanel::Consumer do
|
|
10
10
|
end
|
11
11
|
|
12
12
|
it 'should send a request to api.mixpanel.com/track on events' do
|
13
|
-
stub_request(:any, 'https://api.mixpanel.com/track').to_return({ :body => "1" })
|
13
|
+
stub_request(:any, 'https://api.mixpanel.com/track').to_return({ :body => '{"status": 1, "error": null}' })
|
14
14
|
@consumer.send(:event, {'data' => 'TEST EVENT MESSAGE'}.to_json)
|
15
15
|
WebMock.should have_requested(:post, 'https://api.mixpanel.com/track').
|
16
|
-
with(:body => {'data' => 'IlRFU1QgRVZFTlQgTUVTU0FHRSI=' })
|
16
|
+
with(:body => {'data' => 'IlRFU1QgRVZFTlQgTUVTU0FHRSI=', 'verbose' => '1' })
|
17
17
|
end
|
18
18
|
|
19
19
|
it 'should send a request to api.mixpanel.com/people on profile updates' do
|
20
|
-
stub_request(:any, 'https://api.mixpanel.com/engage').to_return({ :body => "1" })
|
20
|
+
stub_request(:any, 'https://api.mixpanel.com/engage').to_return({ :body => '{"status": 1, "error": null}' })
|
21
21
|
@consumer.send(:profile_update, {'data' => 'TEST EVENT MESSAGE'}.to_json)
|
22
22
|
WebMock.should have_requested(:post, 'https://api.mixpanel.com/engage').
|
23
|
-
with(:body => {'data' => 'IlRFU1QgRVZFTlQgTUVTU0FHRSI=' })
|
23
|
+
with(:body => {'data' => 'IlRFU1QgRVZFTlQgTUVTU0FHRSI=', 'verbose' => '1' })
|
24
24
|
end
|
25
25
|
|
26
26
|
it 'should send a request to api.mixpanel.com/import on event imports' do
|
27
|
-
stub_request(:any, 'https://api.mixpanel.com/import').to_return({ :body => "1" })
|
28
|
-
@consumer.send(:import, {'data' => 'TEST EVENT MESSAGE', 'api_key' => 'API_KEY'}.to_json)
|
27
|
+
stub_request(:any, 'https://api.mixpanel.com/import').to_return({ :body => '{"status": 1, "error": null}' })
|
28
|
+
@consumer.send(:import, {'data' => 'TEST EVENT MESSAGE', 'api_key' => 'API_KEY','verbose' => '1' }.to_json)
|
29
29
|
WebMock.should have_requested(:post, 'https://api.mixpanel.com/import').
|
30
|
-
with(:body => {'data' => 'IlRFU1QgRVZFTlQgTUVTU0FHRSI=', 'api_key' => 'API_KEY' })
|
30
|
+
with(:body => {'data' => 'IlRFU1QgRVZFTlQgTUVTU0FHRSI=', 'api_key' => 'API_KEY', 'verbose' => '1' })
|
31
31
|
end
|
32
32
|
|
33
33
|
it 'should encode long messages without newlines' do
|
34
|
-
stub_request(:any, 'https://api.mixpanel.com/track').to_return({ :body => "1" })
|
34
|
+
stub_request(:any, 'https://api.mixpanel.com/track').to_return({ :body => '{"status": 1, "error": null}' })
|
35
35
|
@consumer.send(:event, { 'data' => 'BASE64-ENCODED VERSION OF BIN. THIS METHOD COMPLIES WITH RFC 2045. LINE FEEDS ARE ADDED TO EVERY 60 ENCODED CHARACTORS. IN RUBY 1.8 WE NEED TO JUST CALL ENCODE64 AND REMOVE THE LINE FEEDS, IN RUBY 1.9 WE CALL STRIC_ENCODED64 METHOD INSTEAD' }.to_json)
|
36
36
|
WebMock.should have_requested(:post, 'https://api.mixpanel.com/track').
|
37
|
-
with(:body => { 'data' => 'IkJBU0U2NC1FTkNPREVEIFZFUlNJT04gT0YgQklOLiBUSElTIE1FVEhPRCBDT01QTElFUyBXSVRIIFJGQyAyMDQ1LiBMSU5FIEZFRURTIEFSRSBBRERFRCBUTyBFVkVSWSA2MCBFTkNPREVEIENIQVJBQ1RPUlMuIElOIFJVQlkgMS44IFdFIE5FRUQgVE8gSlVTVCBDQUxMIEVOQ09ERTY0IEFORCBSRU1PVkUgVEhFIExJTkUgRkVFRFMsIElOIFJVQlkgMS45IFdFIENBTEwgU1RSSUNfRU5DT0RFRDY0IE1FVEhPRCBJTlNURUFEIg==' })
|
37
|
+
with(:body => { 'data' => 'IkJBU0U2NC1FTkNPREVEIFZFUlNJT04gT0YgQklOLiBUSElTIE1FVEhPRCBDT01QTElFUyBXSVRIIFJGQyAyMDQ1LiBMSU5FIEZFRURTIEFSRSBBRERFRCBUTyBFVkVSWSA2MCBFTkNPREVEIENIQVJBQ1RPUlMuIElOIFJVQlkgMS44IFdFIE5FRUQgVE8gSlVTVCBDQUxMIEVOQ09ERTY0IEFORCBSRU1PVkUgVEhFIExJTkUgRkVFRFMsIElOIFJVQlkgMS45IFdFIENBTEwgU1RSSUNfRU5DT0RFRDY0IE1FVEhPRCBJTlNURUFEIg==', 'verbose' => '1' })
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should provide thorough information in case mixpanel fails' do
|
41
|
+
stub_request(:any, 'https://api.mixpanel.com/track').to_return({ :status => 401, :body => "nutcakes" })
|
42
|
+
expect { @consumer.send(:event, {'data' => 'TEST EVENT MESSAGE'}.to_json) }.to raise_exception('Could not write to Mixpanel, server responded with 401 returning: \'nutcakes\'')
|
38
43
|
end
|
39
44
|
end
|
40
45
|
|
@@ -46,28 +51,28 @@ describe Mixpanel::BufferedConsumer do
|
|
46
51
|
end
|
47
52
|
|
48
53
|
it 'should not send a request for a single message until flush is called' do
|
49
|
-
stub_request(:any, 'https://api.mixpanel.com/track').to_return({ :body => "1" })
|
54
|
+
stub_request(:any, 'https://api.mixpanel.com/track').to_return({ :body => '{"status": 1, "error": null}' })
|
50
55
|
@consumer.send(:event, {'data' => 'TEST EVENT 1'}.to_json)
|
51
56
|
WebMock.should have_not_requested(:post, 'https://api.mixpanel.com/track')
|
52
57
|
|
53
58
|
@consumer.flush()
|
54
59
|
WebMock.should have_requested(:post, 'https://api.mixpanel.com/track').
|
55
|
-
with(:body => {'data' => 'WyJURVNUIEVWRU5UIDEiXQ==' })
|
60
|
+
with(:body => {'data' => 'WyJURVNUIEVWRU5UIDEiXQ==', 'verbose' => '1' })
|
56
61
|
end
|
57
62
|
|
58
63
|
it 'should send one message when max_length events are tracked' do
|
59
|
-
stub_request(:any, 'https://api.mixpanel.com/track').to_return({ :body => "1" })
|
64
|
+
stub_request(:any, 'https://api.mixpanel.com/track').to_return({ :body => '{"status": 1, "error": null}' })
|
60
65
|
|
61
66
|
@max_length.times do |i|
|
62
67
|
@consumer.send(:event, {'data' => "x #{i}"}.to_json)
|
63
68
|
end
|
64
69
|
|
65
70
|
WebMock.should have_requested(:post, 'https://api.mixpanel.com/track').
|
66
|
-
with(:body => {'data' => 'WyJ4IDAiLCJ4IDEiLCJ4IDIiLCJ4IDMiLCJ4IDQiLCJ4IDUiLCJ4IDYiLCJ4IDciLCJ4IDgiLCJ4IDkiXQ==' })
|
71
|
+
with(:body => {'data' => 'WyJ4IDAiLCJ4IDEiLCJ4IDIiLCJ4IDMiLCJ4IDQiLCJ4IDUiLCJ4IDYiLCJ4IDciLCJ4IDgiLCJ4IDkiXQ==', 'verbose' => '1' })
|
67
72
|
end
|
68
73
|
|
69
74
|
it 'should send one message per api key on import' do
|
70
|
-
stub_request(:any, 'https://api.mixpanel.com/import').to_return({ :body => "1" })
|
75
|
+
stub_request(:any, 'https://api.mixpanel.com/import').to_return({ :body => '{"status": 1, "error": null}' })
|
71
76
|
@consumer.send(:import, {'data' => 'TEST EVENT 1', 'api_key' => 'KEY 1'}.to_json)
|
72
77
|
@consumer.send(:import, {'data' => 'TEST EVENT 1', 'api_key' => 'KEY 2'}.to_json)
|
73
78
|
@consumer.send(:import, {'data' => 'TEST EVENT 2', 'api_key' => 'KEY 1'}.to_json)
|
@@ -75,9 +80,9 @@ describe Mixpanel::BufferedConsumer do
|
|
75
80
|
@consumer.flush
|
76
81
|
|
77
82
|
WebMock.should have_requested(:post, 'https://api.mixpanel.com/import').
|
78
|
-
with(:body => {'data' => 'IlRFU1QgRVZFTlQgMSI=', 'api_key' => 'KEY 1' })
|
83
|
+
with(:body => {'data' => 'IlRFU1QgRVZFTlQgMSI=', 'api_key' => 'KEY 1', 'verbose' => '1' })
|
79
84
|
|
80
85
|
WebMock.should have_requested(:post, 'https://api.mixpanel.com/import').
|
81
|
-
with(:body => {'data' => 'IlRFU1QgRVZFTlQgMSI=', 'api_key' => 'KEY 2' })
|
86
|
+
with(:body => {'data' => 'IlRFU1QgRVZFTlQgMSI=', 'api_key' => 'KEY 2', 'verbose' => '1' })
|
82
87
|
end
|
83
88
|
end
|
@@ -11,18 +11,18 @@ describe Mixpanel::Tracker do
|
|
11
11
|
|
12
12
|
it 'should send an alias message to mixpanel no matter what the consumer is' do
|
13
13
|
WebMock.reset!
|
14
|
-
stub_request(:any, 'https://api.mixpanel.com/track').to_return({ :body => "1" })
|
14
|
+
stub_request(:any, 'https://api.mixpanel.com/track').to_return({ :body => '{"status": 1, "error": null}' })
|
15
15
|
mixpanel = Mixpanel::Tracker.new('TEST TOKEN') {|*args| }
|
16
16
|
mixpanel.alias('TEST ALIAS', 'TEST ID')
|
17
17
|
|
18
18
|
WebMock.should have_requested(:post, 'https://api.mixpanel.com/track').
|
19
|
-
with(:body => { :data => 'eyJldmVudCI6IiRjcmVhdGVfYWxpYXMiLCJwcm9wZXJ0aWVzIjp7ImRpc3RpbmN0X2lkIjoiVEVTVCBJRCIsImFsaWFzIjoiVEVTVCBBTElBUyIsInRva2VuIjoiVEVTVCBUT0tFTiJ9fQ==' })
|
19
|
+
with(:body => { :data => 'eyJldmVudCI6IiRjcmVhdGVfYWxpYXMiLCJwcm9wZXJ0aWVzIjp7ImRpc3RpbmN0X2lkIjoiVEVTVCBJRCIsImFsaWFzIjoiVEVTVCBBTElBUyIsInRva2VuIjoiVEVTVCBUT0tFTiJ9fQ==', 'verbose' => '1' })
|
20
20
|
end
|
21
21
|
|
22
22
|
it 'should send a request to the track api with the default consumer' do
|
23
23
|
WebMock.reset!
|
24
|
-
stub_request(:any, 'https://api.mixpanel.com/track').to_return({ :body => "1" })
|
25
|
-
stub_request(:any, 'https://api.mixpanel.com/engage').to_return({ :body => "1" })
|
24
|
+
stub_request(:any, 'https://api.mixpanel.com/track').to_return({ :body => '{"status": 1, "error": null}' })
|
25
|
+
stub_request(:any, 'https://api.mixpanel.com/engage').to_return({ :body => '{"status": 1, "error": null}' })
|
26
26
|
mixpanel = Mixpanel::Tracker.new('TEST TOKEN')
|
27
27
|
|
28
28
|
mixpanel.track('TEST ID', 'TEST EVENT', { 'Circumstances' => 'During test' })
|
@@ -31,7 +31,7 @@ describe Mixpanel::Tracker do
|
|
31
31
|
WebMock.should have_requested(:post, 'https://api.mixpanel.com/track').
|
32
32
|
with { |req| body = req.body }
|
33
33
|
|
34
|
-
message_urlencoded = body[/^data=(
|
34
|
+
message_urlencoded = body[/^data=(.*?)(?:&|$)/, 1]
|
35
35
|
message_json = Base64.strict_decode64(URI.unescape(message_urlencoded))
|
36
36
|
message = JSON.load(message_json)
|
37
37
|
message.should eq({
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mixpanel-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.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-10-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|