test_track_rails_client 2.0.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +62 -7
- data/Rakefile +8 -4
- data/app/models/test_track/analytics/mixpanel_client.rb +2 -5
- data/app/models/test_track/analytics/safe_wrapper.rb +4 -4
- data/app/models/test_track/config_updater.rb +2 -2
- data/app/models/test_track/fake/split_registry.rb +2 -2
- data/app/models/test_track/notify_assignment_job.rb +3 -4
- data/app/models/test_track/offline_session.rb +6 -4
- data/app/models/test_track/remote/split_registry.rb +2 -2
- data/app/models/test_track/remote/visitor.rb +2 -2
- data/app/models/test_track/session.rb +12 -73
- data/app/models/test_track/unsynced_assignments_notifier.rb +2 -4
- data/app/models/test_track/vary_dsl.rb +5 -1
- data/app/models/test_track/visitor.rb +0 -11
- data/lib/test_track_rails_client/version.rb +1 -1
- data/vendor/gems/fakeable_her/fakeable_her.gemspec +2 -3
- data/vendor/gems/her/her.gemspec +4 -5
- data/vendor/gems/her/lib/her/api.rb +1 -1
- data/vendor/gems/her/lib/her/model/associations/association_proxy.rb +1 -2
- data/vendor/gems/her/lib/her/model/orm.rb +41 -29
- data/vendor/gems/her/lib/her/model/parse.rb +1 -0
- data/vendor/gems/her/lib/her/model/relation.rb +21 -6
- data/vendor/gems/her/lib/her/version.rb +1 -1
- metadata +52 -139
- data/app/models/test_track/create_alias_job.rb +0 -18
- data/vendor/gems/her/CONTRIBUTING.md +0 -26
- data/vendor/gems/her/Gemfile +0 -10
- data/vendor/gems/her/README.md +0 -1023
- data/vendor/gems/her/Rakefile +0 -11
- data/vendor/gems/her/UPGRADE.md +0 -101
- data/vendor/gems/her/gemfiles/Gemfile.activemodel-3.2.x +0 -7
- data/vendor/gems/her/gemfiles/Gemfile.activemodel-4.0 +0 -7
- data/vendor/gems/her/gemfiles/Gemfile.activemodel-4.1 +0 -7
- data/vendor/gems/her/gemfiles/Gemfile.activemodel-4.2 +0 -7
- data/vendor/gems/her/spec/api_spec.rb +0 -114
- data/vendor/gems/her/spec/collection_spec.rb +0 -26
- data/vendor/gems/her/spec/error_collection_spec.rb +0 -33
- data/vendor/gems/her/spec/json_api/model_spec.rb +0 -168
- data/vendor/gems/her/spec/middleware/accept_json_spec.rb +0 -10
- data/vendor/gems/her/spec/middleware/first_level_parse_json_spec.rb +0 -62
- data/vendor/gems/her/spec/middleware/json_api_parser_spec.rb +0 -32
- data/vendor/gems/her/spec/middleware/second_level_parse_json_spec.rb +0 -35
- data/vendor/gems/her/spec/model/associations/association_proxy_spec.rb +0 -31
- data/vendor/gems/her/spec/model/associations_spec.rb +0 -504
- data/vendor/gems/her/spec/model/attributes_spec.rb +0 -404
- data/vendor/gems/her/spec/model/callbacks_spec.rb +0 -145
- data/vendor/gems/her/spec/model/dirty_spec.rb +0 -110
- data/vendor/gems/her/spec/model/http_spec.rb +0 -165
- data/vendor/gems/her/spec/model/introspection_spec.rb +0 -76
- data/vendor/gems/her/spec/model/nested_attributes_spec.rb +0 -134
- data/vendor/gems/her/spec/model/orm_spec.rb +0 -791
- data/vendor/gems/her/spec/model/parse_spec.rb +0 -372
- data/vendor/gems/her/spec/model/paths_spec.rb +0 -347
- data/vendor/gems/her/spec/model/relation_spec.rb +0 -226
- data/vendor/gems/her/spec/model/validations_spec.rb +0 -42
- data/vendor/gems/her/spec/model_spec.rb +0 -31
- data/vendor/gems/her/spec/spec_helper.rb +0 -27
- data/vendor/gems/her/spec/support/extensions/array.rb +0 -5
- data/vendor/gems/her/spec/support/extensions/hash.rb +0 -5
- data/vendor/gems/her/spec/support/macros/her_macros.rb +0 -17
- data/vendor/gems/her/spec/support/macros/model_macros.rb +0 -36
- data/vendor/gems/her/spec/support/macros/request_macros.rb +0 -27
- data/vendor/gems/publicsuffix-ruby/CHANGELOG.md +0 -236
- data/vendor/gems/publicsuffix-ruby/Gemfile +0 -3
- data/vendor/gems/publicsuffix-ruby/LICENSE.txt +0 -22
- data/vendor/gems/publicsuffix-ruby/README.md +0 -151
- data/vendor/gems/publicsuffix-ruby/Rakefile +0 -109
- data/vendor/gems/publicsuffix-ruby/lib/definitions.txt +0 -11467
- data/vendor/gems/publicsuffix-ruby/lib/public_suffix/domain.rb +0 -387
- data/vendor/gems/publicsuffix-ruby/lib/public_suffix/errors.rb +0 -53
- data/vendor/gems/publicsuffix-ruby/lib/public_suffix/list.rb +0 -302
- data/vendor/gems/publicsuffix-ruby/lib/public_suffix/rule.rb +0 -373
- data/vendor/gems/publicsuffix-ruby/lib/public_suffix/version.rb +0 -23
- data/vendor/gems/publicsuffix-ruby/lib/public_suffix.rb +0 -131
- data/vendor/gems/publicsuffix-ruby/public_suffix.gemspec +0 -39
- data/vendor/gems/publicsuffix-ruby/test/acceptance_test.rb +0 -42
- data/vendor/gems/publicsuffix-ruby/test/test_helper.rb +0 -6
- data/vendor/gems/publicsuffix-ruby/test/unit/domain_test.rb +0 -170
- data/vendor/gems/publicsuffix-ruby/test/unit/errors_test.rb +0 -23
- data/vendor/gems/publicsuffix-ruby/test/unit/list_test.rb +0 -179
- data/vendor/gems/publicsuffix-ruby/test/unit/public_suffix_test.rb +0 -115
- data/vendor/gems/publicsuffix-ruby/test/unit/rule_test.rb +0 -307
- data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/capybara_configuration.rb +0 -98
- data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/matchers.rb +0 -151
- data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/rspec_configuration.rb +0 -34
- data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/rubocop/cop/betterment/html_safe.rb +0 -15
- data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/rubocop/cop/betterment/raw.rb +0 -15
- data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/rubocop/cop/betterment/safe_concat.rb +0 -15
- data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/rubocop.rb +0 -3
- data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/shared_examples/betterment_application_examples.rb +0 -43
- data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/shared_examples.rb +0 -1
- data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/site_prism_configuration.rb +0 -42
- data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/site_prism_dropdown.rb +0 -17
- data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/version.rb +0 -3
- data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/webmock_configuration.rb +0 -8
- data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers.rb +0 -2
- data/vendor/gems/ruby_spec_helpers/ruby_spec_helpers.gemspec +0 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6eefba329c2d3bcbf7e2ec64800ac65ae8d5b389
|
4
|
+
data.tar.gz: 9227d7cca55324a963b399c65d48088d917b143e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9496d2f71697004936ed0896e6805d32723b067ea93c6915ec07ac75b81371e1ddd2b0b697961f7ba188a22f77d45abe912e7b306355c34d449af4ef16bfd9bb
|
7
|
+
data.tar.gz: 4981fc0c2992de2469ff3d82b45a8a24af5d1dcef4ae70aa0dd615e77c4519c0210eba62f5b39b5239b8d5383dc53c49b41e2f3c9710bd4c374f4b4dc042c329
|
data/README.md
CHANGED
@@ -15,7 +15,7 @@ If you're looking to do client-side assignment, then check out our [JS client](h
|
|
15
15
|
* [Tracking visitor logins](#tracking-visitor-logins)
|
16
16
|
* [Tracking signups](#tracking-signups)
|
17
17
|
* [Testing splits](#testing-splits)
|
18
|
-
* [
|
18
|
+
* [Analytics](#analytics)
|
19
19
|
* [Upgrading](#upgrading)
|
20
20
|
* [How to Contribute](#how-to-contribute)
|
21
21
|
|
@@ -335,8 +335,9 @@ it "shows the right info" do
|
|
335
335
|
end
|
336
336
|
```
|
337
337
|
|
338
|
-
##
|
339
|
-
|
338
|
+
## Analytics
|
339
|
+
|
340
|
+
TestTrack does not offer built-in functionality for analyzing the results of split tests. TestTrack does provide hooks to easily integrate with your preferred analytics tool. By default, TestTrack will use Mixpanel as an analytics backend. If you wish to use another tool, you can set the `analytics` attribute on `TestTrack` with your custom client. You should do this in a Rails initializer.
|
340
341
|
|
341
342
|
```ruby
|
342
343
|
# config/initializers/test_track.rb
|
@@ -350,18 +351,72 @@ Your client must implement the following methods:
|
|
350
351
|
#
|
351
352
|
# @param visitor_id [String] TestTrack's unique visitor identification key
|
352
353
|
# @param assignment [TestTrack::Assignment] The assignment model itself
|
353
|
-
|
354
|
-
def track_assignment(visitor_id, assignment, properties)
|
354
|
+
def track_assignment(visitor_id, assignment)
|
355
355
|
|
356
356
|
# Called after TestTrack.sign_up!
|
357
357
|
#
|
358
358
|
# @param visitor_id [String] TestTrack's unique visitor identification key
|
359
|
-
|
360
|
-
|
359
|
+
def sign_up!(visitor_id)
|
360
|
+
```
|
361
|
+
|
362
|
+
### Using TestTrack with a new analytics tool
|
363
|
+
|
364
|
+
TestTrack manages its own visitor identifier which is different from the identifier of your analytics tool. We recommend using TestTrack's visitor identifier as your analytics identifier when possible. Within TestTrack Rails Client, assignment events will trigger a call to `TestTrack.analytics.track_assignment` with a TestTrack visitor identifier. To ensure that analytics events coming from within the browser have the right identifier, you must set the identifier when your analytics javascript library is loaded.
|
365
|
+
|
366
|
+
Here's an example for how to do it with Mixpanel:
|
367
|
+
|
368
|
+
```javascript
|
369
|
+
mixpanel.init('YOUR MIXPANEL TOKEN', {
|
370
|
+
loaded: function(mixpanel) {
|
371
|
+
mixpanel.identify('<%= test_track_visitor.id %>');
|
372
|
+
}
|
373
|
+
});
|
374
|
+
```
|
375
|
+
|
376
|
+
### Using TestTrack with an existing analytics tool
|
377
|
+
|
378
|
+
In cases where you have already established identities with your analytics tool, you can use TestTrack's hooks to link TestTrack's visitor identifier to your analytics identifier.
|
379
|
+
|
380
|
+
Using Mixpanel as an example, you must call [`mixpanel.alias`](https://mixpanel.com/help/questions/articles/assigning-your-own-unique-ids-to-users) with the visitor's analytics identifier and their TestTrack visitor identifier. This will establish a link between those two identifiers within your analytics tool, allowing you to analyze your funnels. We recommend using a thread-local storage like [`RequestStore`](https://github.com/steveklabnik/request_store) to make your identifier available to the TestTrack analytics client.
|
381
|
+
|
382
|
+
In your controller, store the Mixpanel distinct ID in the RequestStore.
|
383
|
+
|
384
|
+
```ruby
|
385
|
+
class ApplicationController < ActionController::Base
|
386
|
+
before_action :store_mixpanel_distinct_id
|
387
|
+
|
388
|
+
def store_mixpanel_distinct_id
|
389
|
+
RequestStore[:mixpanel_distinct_id] = cookies["mp_#{ENV['MIXPANEL_TOKEN']}_mixpanel"]
|
390
|
+
end
|
391
|
+
end
|
392
|
+
```
|
393
|
+
|
394
|
+
Then in your custom analytics plugin, use that value for assignment events and aliasing.
|
395
|
+
|
396
|
+
```ruby
|
397
|
+
def track_assignment!(visitor_id)
|
398
|
+
identifier = RequestStore[:mixpanel_distinct_id] || visitor_id
|
399
|
+
properties = {
|
400
|
+
SplitName: assignment.split_name,
|
401
|
+
SplitVariant: assignment.variant,
|
402
|
+
SplitContext: assignment.context
|
403
|
+
}
|
404
|
+
|
405
|
+
mixpanel.track(identifier, 'SplitAssigned', properties)
|
406
|
+
end
|
407
|
+
|
408
|
+
def sign_up!(visitor_id)
|
409
|
+
mixpanel.alias(visitor_id, RequestStore[:mixpanel_distinct_id])
|
410
|
+
end
|
361
411
|
```
|
362
412
|
|
363
413
|
## Upgrading
|
364
414
|
|
415
|
+
### From 2.0 to 3.0
|
416
|
+
|
417
|
+
TestTrack Rails Client no longer manages your Mixpanel cookie. The analytics plugin now provides a callback on `sign_up!` that will allow you to implement this functionality within your application. Please see the [analytics documentation](#analytics) for more details.
|
418
|
+
The TestTrack.analytics client `#track_assignment` method no longer accepts a properties hash as an argument as `mixpanel_distinct_id` is no longer relevant.
|
419
|
+
|
365
420
|
### From 1.x to 1.3
|
366
421
|
|
367
422
|
`TestTrack::Session#log_in!` and `TestTrack:Session#sign_up!` now take a `TestTrack::Identity` instance argument instead of an identity type and identity value.
|
data/Rakefile
CHANGED
@@ -36,30 +36,34 @@ task :vendor_deps do
|
|
36
36
|
FileUtils.module_eval do
|
37
37
|
cd "vendor/gems" do
|
38
38
|
rm_r Dir.glob('*')
|
39
|
-
%w(
|
39
|
+
%w(her fakeable_her).each do |repo|
|
40
40
|
`git clone --depth=1 git@github.com:Betterment/#{repo}.git && rm -rf #{repo}/.git`
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
-
cd "vendor/gems/
|
44
|
+
cd "vendor/gems/her" do
|
45
45
|
rm_r(Dir.glob('.*') - %w(. ..))
|
46
46
|
rm_r Dir.glob('*.md')
|
47
47
|
rm_r %w(
|
48
|
+
Appraisals
|
48
49
|
Gemfile
|
49
50
|
Gemfile.lock
|
51
|
+
Rakefile
|
52
|
+
gemfiles
|
50
53
|
spec
|
51
54
|
), force: true
|
52
|
-
`sed -E -i '' '/license/d' ruby_spec_helpers.gemspec`
|
53
55
|
end
|
54
56
|
|
55
57
|
cd "vendor/gems/fakeable_her" do
|
56
58
|
rm_r(Dir.glob('.*') - %w(. ..))
|
57
59
|
rm_r Dir.glob('*.md')
|
58
60
|
rm_r %w(
|
61
|
+
Appraisals
|
59
62
|
Gemfile
|
60
63
|
Gemfile.lock
|
61
64
|
Rakefile
|
62
65
|
bin
|
66
|
+
gemfiles
|
63
67
|
spec
|
64
68
|
), force: true
|
65
69
|
`sed -E -i '' '/license/d' fakeable_her.gemspec`
|
@@ -70,7 +74,7 @@ end
|
|
70
74
|
|
71
75
|
task(:default).clear
|
72
76
|
if ENV['APPRAISAL_INITIALIZED'] || ENV['TRAVIS']
|
73
|
-
task default:
|
77
|
+
task default: %i(rubocop spec)
|
74
78
|
else
|
75
79
|
require 'appraisal'
|
76
80
|
Appraisal::Task.new
|
@@ -1,10 +1,7 @@
|
|
1
1
|
module TestTrack::Analytics
|
2
2
|
class MixpanelClient
|
3
|
-
|
4
|
-
|
5
|
-
def track_assignment(visitor_id, assignment, params = {})
|
6
|
-
distinct_id = params.delete(:mixpanel_distinct_id) || visitor_id
|
7
|
-
mixpanel.track(distinct_id, 'SplitAssigned', split_properties(assignment).merge(TTVisitorID: visitor_id))
|
3
|
+
def track_assignment(visitor_id, assignment)
|
4
|
+
mixpanel.track(visitor_id, 'SplitAssigned', split_properties(assignment).merge(TTVisitorID: visitor_id))
|
8
5
|
end
|
9
6
|
|
10
7
|
private
|
@@ -12,12 +12,12 @@ module TestTrack::Analytics
|
|
12
12
|
@error_handler = handler
|
13
13
|
end
|
14
14
|
|
15
|
-
def track_assignment(visitor_id, assignment
|
16
|
-
safe_action { underlying.track_assignment(visitor_id, assignment
|
15
|
+
def track_assignment(visitor_id, assignment)
|
16
|
+
safe_action { underlying.track_assignment(visitor_id, assignment) }
|
17
17
|
end
|
18
18
|
|
19
|
-
def
|
20
|
-
safe_action { underlying.
|
19
|
+
def sign_up!(visitor_id)
|
20
|
+
safe_action { underlying.sign_up!(visitor_id) } if underlying.respond_to?(:sign_up!)
|
21
21
|
end
|
22
22
|
|
23
23
|
private
|
@@ -1,5 +1,5 @@
|
|
1
1
|
class TestTrack::ConfigUpdater
|
2
|
-
def initialize(schema_file_path =
|
2
|
+
def initialize(schema_file_path = Rails.root.join('db', 'test_track_schema.yml'))
|
3
3
|
@schema_file_path = schema_file_path
|
4
4
|
end
|
5
5
|
|
@@ -86,7 +86,7 @@ class TestTrack::ConfigUpdater
|
|
86
86
|
end
|
87
87
|
|
88
88
|
def schema_file_hash
|
89
|
-
@schema_hash ||= YAML.
|
89
|
+
@schema_hash ||= YAML.safe_load(schema_file_contents) || {}
|
90
90
|
end
|
91
91
|
|
92
92
|
def schema_file_contents
|
@@ -39,7 +39,7 @@ class TestTrack::Fake::SplitRegistry
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def test_track_schema_yml_path
|
42
|
-
ENV["TEST_TRACK_SCHEMA_FILE_PATH"] ||
|
42
|
+
ENV["TEST_TRACK_SCHEMA_FILE_PATH"] || Rails.root.join('db', 'test_track_schema.yml')
|
43
43
|
end
|
44
44
|
|
45
45
|
def splits_with_deterministic_weights
|
@@ -47,7 +47,7 @@ class TestTrack::Fake::SplitRegistry
|
|
47
47
|
default_variant = weighting_registry.keys.sort.first
|
48
48
|
|
49
49
|
adjusted_weights = { default_variant => 100 }
|
50
|
-
weighting_registry.except(default_variant).
|
50
|
+
weighting_registry.except(default_variant).each_key do |variant|
|
51
51
|
adjusted_weights[variant] = 0
|
52
52
|
end
|
53
53
|
|
@@ -1,13 +1,12 @@
|
|
1
1
|
class TestTrack::NotifyAssignmentJob
|
2
|
-
attr_reader :
|
2
|
+
attr_reader :visitor_id, :assignment
|
3
3
|
|
4
4
|
def initialize(opts)
|
5
5
|
@visitor_id = opts.delete(:visitor_id)
|
6
|
-
@mixpanel_distinct_id = opts.delete(:mixpanel_distinct_id)
|
7
6
|
@assignment = opts.delete(:assignment)
|
8
7
|
|
9
8
|
%w(visitor_id assignment).each do |param_name|
|
10
|
-
raise "#{param_name} must be present"
|
9
|
+
raise "#{param_name} must be present" if send(param_name).blank?
|
11
10
|
end
|
12
11
|
raise "unknown opts: #{opts.keys.to_sentence}" if opts.present?
|
13
12
|
end
|
@@ -25,7 +24,7 @@ class TestTrack::NotifyAssignmentJob
|
|
25
24
|
|
26
25
|
def track
|
27
26
|
return "failure" unless TestTrack.enabled?
|
28
|
-
result = TestTrack.analytics.track_assignment(visitor_id, assignment
|
27
|
+
result = TestTrack.analytics.track_assignment(visitor_id, assignment)
|
29
28
|
result ? "success" : "failure"
|
30
29
|
end
|
31
30
|
end
|
@@ -45,9 +45,11 @@ class TestTrack::OfflineSession
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def notify_unsynced_assignments!
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
48
|
+
if unsynced_assignments?
|
49
|
+
TestTrack::UnsyncedAssignmentsNotifier.new(
|
50
|
+
visitor_id: visitor.id,
|
51
|
+
assignments: visitor.unsynced_assignments
|
52
|
+
).notify
|
53
|
+
end
|
52
54
|
end
|
53
55
|
end
|
@@ -26,9 +26,9 @@ class TestTrack::Remote::SplitRegistry
|
|
26
26
|
if faked?
|
27
27
|
instance.attributes.freeze
|
28
28
|
else
|
29
|
-
Rails.cache.fetch(CACHE_KEY, expires_in: 5.seconds)
|
29
|
+
Rails.cache.fetch(CACHE_KEY, expires_in: 5.seconds) {
|
30
30
|
instance.attributes
|
31
|
-
|
31
|
+
}.freeze
|
32
32
|
end
|
33
33
|
rescue *TestTrack::SERVER_ERRORS => e
|
34
34
|
Rails.logger.error "TestTrack failed to load split registry. #{e}"
|
@@ -6,8 +6,8 @@ class TestTrack::Remote::Visitor
|
|
6
6
|
has_many :assignments
|
7
7
|
|
8
8
|
def self.from_identifier(identifier_type, identifier_value)
|
9
|
-
raise "must provide an identifier_type"
|
10
|
-
raise "must provide an identifier_value"
|
9
|
+
raise "must provide an identifier_type" if identifier_type.blank?
|
10
|
+
raise "must provide an identifier_value" if identifier_value.blank?
|
11
11
|
|
12
12
|
# TODO: FakeableHer needs to make this faking a feature of `get`
|
13
13
|
if faked?
|
@@ -14,7 +14,6 @@ class TestTrack::Session
|
|
14
14
|
manage_cookies!
|
15
15
|
manage_response_headers!
|
16
16
|
notify_unsynced_assignments! if sync_assignments?
|
17
|
-
create_alias! if signed_up?
|
18
17
|
end
|
19
18
|
|
20
19
|
def visitor_dsl
|
@@ -31,42 +30,27 @@ class TestTrack::Session
|
|
31
30
|
}
|
32
31
|
end
|
33
32
|
|
34
|
-
def log_in!(
|
35
|
-
|
33
|
+
def log_in!(identity, forget_current_visitor: nil)
|
34
|
+
identifier_type = identity.test_track_identifier_type
|
35
|
+
identifier_value = identity.test_track_identifier_value
|
36
36
|
|
37
|
-
|
38
|
-
identity = args[0]
|
39
|
-
identifier_type = identity.test_track_identifier_type
|
40
|
-
identifier_value = identity.test_track_identifier_value
|
41
|
-
else
|
42
|
-
identifier_type = args[0]
|
43
|
-
identifier_value = args[1]
|
44
|
-
warn "#log_in! with two args is deprecated. Please provide a TestTrack::Identity"
|
45
|
-
end
|
46
|
-
|
47
|
-
@visitor = TestTrack::Visitor.new if opts[:forget_current_visitor]
|
37
|
+
@visitor = TestTrack::Visitor.new if forget_current_visitor
|
48
38
|
visitor.link_identifier!(identifier_type, identifier_value)
|
49
39
|
|
50
40
|
identities << identity if identity.present?
|
51
|
-
self.mixpanel_distinct_id = visitor.id
|
52
41
|
true
|
53
42
|
end
|
54
43
|
|
55
|
-
def sign_up!(
|
56
|
-
|
57
|
-
|
58
|
-
identifier_type = identity.test_track_identifier_type
|
59
|
-
identifier_value = identity.test_track_identifier_value
|
60
|
-
else
|
61
|
-
identifier_type = args[0]
|
62
|
-
identifier_value = args[1]
|
63
|
-
warn "#sign_up! with two args is deprecated. Please provide a TestTrack::Identity"
|
64
|
-
end
|
44
|
+
def sign_up!(identity)
|
45
|
+
identifier_type = identity.test_track_identifier_type
|
46
|
+
identifier_value = identity.test_track_identifier_value
|
65
47
|
|
66
48
|
visitor.link_identifier!(identifier_type, identifier_value)
|
67
|
-
|
68
49
|
identities << identity if identity.present?
|
69
|
-
|
50
|
+
|
51
|
+
TestTrack.analytics.sign_up!(visitor.id)
|
52
|
+
|
53
|
+
true
|
70
54
|
end
|
71
55
|
|
72
56
|
def has_matching_identity?(identity)
|
@@ -75,8 +59,7 @@ class TestTrack::Session
|
|
75
59
|
|
76
60
|
private
|
77
61
|
|
78
|
-
attr_reader :controller
|
79
|
-
alias signed_up? signed_up
|
62
|
+
attr_reader :controller
|
80
63
|
|
81
64
|
def visitor
|
82
65
|
@visitor ||= TestTrack::Visitor.new(id: visitor_id)
|
@@ -127,7 +110,6 @@ class TestTrack::Session
|
|
127
110
|
end
|
128
111
|
|
129
112
|
def manage_cookies!
|
130
|
-
set_cookie(mixpanel_cookie_name, mixpanel_cookie.to_json)
|
131
113
|
set_cookie(visitor_cookie_name, visitor.id)
|
132
114
|
end
|
133
115
|
|
@@ -157,7 +139,6 @@ class TestTrack::Session
|
|
157
139
|
|
158
140
|
def notify_unsynced_assignments!
|
159
141
|
payload = {
|
160
|
-
mixpanel_distinct_id: mixpanel_distinct_id,
|
161
142
|
visitor_id: visitor.id,
|
162
143
|
assignments: visitor.unsynced_assignments
|
163
144
|
}
|
@@ -171,52 +152,10 @@ class TestTrack::Session
|
|
171
152
|
end
|
172
153
|
end
|
173
154
|
|
174
|
-
def create_alias!
|
175
|
-
create_alias_job = TestTrack::CreateAliasJob.new(
|
176
|
-
existing_id: mixpanel_distinct_id,
|
177
|
-
alias_id: visitor.id
|
178
|
-
)
|
179
|
-
Delayed::Job.enqueue(create_alias_job)
|
180
|
-
end
|
181
|
-
|
182
155
|
def sync_assignments?
|
183
156
|
visitor.loaded? && visitor.unsynced_assignments.present?
|
184
157
|
end
|
185
158
|
|
186
|
-
def mixpanel_distinct_id
|
187
|
-
mixpanel_cookie['distinct_id']
|
188
|
-
end
|
189
|
-
|
190
|
-
def mixpanel_distinct_id=(value)
|
191
|
-
mixpanel_cookie['distinct_id'] = value
|
192
|
-
end
|
193
|
-
|
194
|
-
def mixpanel_cookie
|
195
|
-
@mixpanel_cookie ||= read_mixpanel_cookie || generate_mixpanel_cookie
|
196
|
-
end
|
197
|
-
|
198
|
-
def read_mixpanel_cookie
|
199
|
-
mixpanel_cookie = cookies[mixpanel_cookie_name]
|
200
|
-
begin
|
201
|
-
JSON.parse(mixpanel_cookie) if mixpanel_cookie
|
202
|
-
rescue JSON::ParserError
|
203
|
-
Rails.logger.error("malformed mixpanel JSON from cookie #{URI.unescape(mixpanel_cookie)}")
|
204
|
-
nil
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
def generate_mixpanel_cookie
|
209
|
-
{ 'distinct_id' => visitor.id }
|
210
|
-
end
|
211
|
-
|
212
|
-
def mixpanel_token
|
213
|
-
ENV['MIXPANEL_TOKEN'] || raise("ENV['MIXPANEL_TOKEN'] must be set")
|
214
|
-
end
|
215
|
-
|
216
|
-
def mixpanel_cookie_name
|
217
|
-
"mp_#{mixpanel_token}_mixpanel"
|
218
|
-
end
|
219
|
-
|
220
159
|
def visitor_cookie_name
|
221
160
|
ENV['TEST_TRACK_VISITOR_COOKIE_NAME'] || 'tt_visitor_id'
|
222
161
|
end
|
@@ -1,13 +1,12 @@
|
|
1
1
|
class TestTrack::UnsyncedAssignmentsNotifier
|
2
|
-
attr_reader :
|
2
|
+
attr_reader :visitor_id, :assignments
|
3
3
|
|
4
4
|
def initialize(opts)
|
5
5
|
@visitor_id = opts.delete(:visitor_id)
|
6
|
-
@mixpanel_distinct_id = opts.delete(:mixpanel_distinct_id) || visitor_id
|
7
6
|
@assignments = opts.delete(:assignments)
|
8
7
|
|
9
8
|
%w(visitor_id assignments).each do |param_name|
|
10
|
-
raise "#{param_name} must be present"
|
9
|
+
raise "#{param_name} must be present" if send(param_name).blank?
|
11
10
|
end
|
12
11
|
raise "unknown opts: #{opts.keys.to_sentence}" if opts.present?
|
13
12
|
end
|
@@ -29,7 +28,6 @@ class TestTrack::UnsyncedAssignmentsNotifier
|
|
29
28
|
|
30
29
|
def build_notify_assignment_job(assignment)
|
31
30
|
TestTrack::NotifyAssignmentJob.new(
|
32
|
-
mixpanel_distinct_id: mixpanel_distinct_id,
|
33
31
|
visitor_id: visitor_id,
|
34
32
|
assignment: assignment
|
35
33
|
)
|
@@ -17,7 +17,7 @@ class TestTrack::VaryDSL
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def when(*variants, &block)
|
20
|
-
raise ArgumentError, "must provide at least one variant"
|
20
|
+
raise ArgumentError, "must provide at least one variant" if variants.blank?
|
21
21
|
variants.each do |variant|
|
22
22
|
assign_behavior_to_variant(variant, block)
|
23
23
|
end
|
@@ -57,6 +57,10 @@ class TestTrack::VaryDSL
|
|
57
57
|
variant = variant.to_s
|
58
58
|
|
59
59
|
raise ArgumentError, "must provide block for #{variant}" unless behavior_proc
|
60
|
+
notify_because_vary(<<-MESSAGE) if variant_behaviors.include?(variant)
|
61
|
+
configures variant "#{variant}" more than once.
|
62
|
+
This will raise an error in the next version of test_track_rails_client.
|
63
|
+
MESSAGE
|
60
64
|
notify_because_vary "configures unknown variant \"#{variant}\"" unless variant_acceptable?(variant)
|
61
65
|
|
62
66
|
variant_behaviors[variant] = behavior_proc
|
@@ -79,17 +79,6 @@ class TestTrack::Visitor
|
|
79
79
|
end
|
80
80
|
end
|
81
81
|
|
82
|
-
def self.backfill_identity(opts)
|
83
|
-
remote_identifier_visitor = TestTrack::Remote::Visitor.from_identifier(opts[:identifier_type], opts[:identifier_value])
|
84
|
-
visitor = new(
|
85
|
-
id: remote_identifier_visitor.id,
|
86
|
-
assignments: remote_identifier_visitor.assignments
|
87
|
-
)
|
88
|
-
|
89
|
-
TestTrack::CreateAliasJob.new(existing_id: opts[:existing_id], alias_id: visitor.id).perform
|
90
|
-
visitor
|
91
|
-
end
|
92
|
-
|
93
82
|
def offline?
|
94
83
|
@tt_offline
|
95
84
|
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
# coding: utf-8
|
2
1
|
lib = File.expand_path('../lib', __FILE__)
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
3
|
require 'fakeable_her/version'
|
@@ -16,7 +15,7 @@ Gem::Specification.new do |spec|
|
|
16
15
|
spec.require_paths = ["lib"]
|
17
16
|
|
18
17
|
spec.add_dependency 'her'
|
19
|
-
spec.add_dependency 'rails', '
|
18
|
+
spec.add_dependency 'rails', '>= 4.1', '< 5.2'
|
20
19
|
|
21
|
-
spec.add_development_dependency '
|
20
|
+
spec.add_development_dependency 'appraisal', '~> 2.2.0'
|
22
21
|
end
|
data/vendor/gems/her/her.gemspec
CHANGED
@@ -18,14 +18,13 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.require_paths = ["lib"]
|
19
19
|
|
20
20
|
s.add_development_dependency "rake", "~> 10.0"
|
21
|
-
s.add_development_dependency "rspec", "~>
|
22
|
-
s.add_development_dependency "rspec-its", "~> 1.0"
|
23
|
-
s.add_development_dependency "fivemat", "~> 1.2"
|
21
|
+
s.add_development_dependency "rspec", "~> 3.5"
|
24
22
|
s.add_development_dependency "json", "~> 1.8"
|
25
23
|
s.add_development_dependency "pry"
|
24
|
+
s.add_development_dependency 'appraisal', '~> 2.2.0'
|
26
25
|
|
27
|
-
s.add_runtime_dependency "activemodel", ">= 3.0.0", "<=
|
28
|
-
s.add_runtime_dependency "activesupport", ">= 3.0.0", "<=
|
26
|
+
s.add_runtime_dependency "activemodel", ">= 3.0.0", "<= 6.0.0"
|
27
|
+
s.add_runtime_dependency "activesupport", ">= 3.0.0", "<= 6.0.0"
|
29
28
|
s.add_runtime_dependency "faraday", ">= 0.8", "< 1.0"
|
30
29
|
s.add_runtime_dependency "multi_json", "~> 1.7"
|
31
30
|
end
|
@@ -6,7 +6,7 @@ module Her
|
|
6
6
|
attr_reader :connection, :options
|
7
7
|
|
8
8
|
# Constants
|
9
|
-
FARADAY_OPTIONS = [:request, :proxy, :ssl, :builder, :url, :parallel_manager, :params, :headers, :builder_class].freeze
|
9
|
+
FARADAY_OPTIONS = [:request, :proxy, :ssl, :builder, :url, :parallel_manager, :params, :headers, :builder_class, :timeout, :open_timeout].freeze
|
10
10
|
|
11
11
|
# Setup a default API connection. Accepted arguments and options are the same as {API#setup}.
|
12
12
|
def self.setup(opts={}, &block)
|
@@ -33,8 +33,7 @@ module Her
|
|
33
33
|
end
|
34
34
|
|
35
35
|
# create a proxy to the fetched object's method
|
36
|
-
|
37
|
-
metaclass.install_proxy_methods 'association.fetch', name
|
36
|
+
AssociationProxy.install_proxy_methods 'association.fetch', name
|
38
37
|
|
39
38
|
# resend message to fetched object
|
40
39
|
__send__(name, *args, &block)
|