test_track_rails_client 1.2.0 → 1.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 +4 -4
- data/README.md +17 -0
- data/app/controllers/concerns/test_track/controller.rb +1 -1
- data/app/models/concerns/test_track/identity.rb +19 -39
- data/app/models/test_track/identity_session_discriminator.rb +25 -12
- data/app/models/test_track/session.rb +36 -2
- data/app/models/test_track/session_identity_collection.rb +29 -0
- data/lib/test_track_rails_client/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 30685a58f06262e141d5deb48bce124da381861e
|
4
|
+
data.tar.gz: 22c790111f624535e1165bba5ad83b68b765944b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7452da90b5d34c19107e6a446908fd48034e094997b0c40f612b9fdf4c3c10b0c7f80779eed9981294184c7982f39919a83b5086671b47bf42970dc2adca3106
|
7
|
+
data.tar.gz: 805507d3629c7cd387a0f90604a9e0725fa234360bd4d575a84a7f756c698440a39d088f29cc0dd642ff2bb9da947b581600d1584f6432a6cef07820a75634f6
|
data/README.md
CHANGED
@@ -8,6 +8,17 @@ It provides server-side split-testing and feature-toggling through a simple API.
|
|
8
8
|
|
9
9
|
If you're looking to do client-side assignment, then check out our [JS client](https://github.com/Betterment/test_track_js_client).
|
10
10
|
|
11
|
+
* [Installation](#installation)
|
12
|
+
* [Concepts](#concepts)
|
13
|
+
* [Configuring the TestTrack server from your app](#configuring-the-testtrack-server-from-your-app)
|
14
|
+
* [Varying app behavior based on assigned variant](#varying-app-behavior-based-on-assigned-variant)
|
15
|
+
* [Tracking visitor logins](#tracking-visitor-logins)
|
16
|
+
* [Tracking signups](#tracking-signups)
|
17
|
+
* [Testing splits](#testing-splits)
|
18
|
+
* [Custom Analytics](#custom-analytics)
|
19
|
+
* [Upgrading](#upgrading)
|
20
|
+
* [How to Contribute](#how-to-contribute)
|
21
|
+
|
11
22
|
## Installation
|
12
23
|
|
13
24
|
Install the gem:
|
@@ -349,6 +360,12 @@ def track_assignment(visitor_id, assignment, properties)
|
|
349
360
|
def alias(visitor_id, existing_id)
|
350
361
|
```
|
351
362
|
|
363
|
+
## Upgrading
|
364
|
+
|
365
|
+
### From 1.x to 1.3
|
366
|
+
|
367
|
+
`TestTrack::Session#log_in!` and `TestTrack:Session#sign_up!` now take a `TestTrack::Identity` instance argument instead of an identity type and identity value.
|
368
|
+
|
352
369
|
## How to Contribute
|
353
370
|
|
354
371
|
We would love for you to contribute! Anything that benefits the majority of `test_track` users—from a documentation fix to an entirely new feature—is encouraged.
|
@@ -2,74 +2,54 @@ module TestTrack::Identity
|
|
2
2
|
extend ActiveSupport::Concern
|
3
3
|
|
4
4
|
module ClassMethods
|
5
|
-
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
6
|
-
def test_track_identifier(identifier_type, identifier_value_method)
|
5
|
+
def test_track_identifier(identifier_type, identifier_value_method) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
7
6
|
instance_methods = Module.new
|
8
7
|
include instance_methods
|
9
8
|
|
10
9
|
instance_methods.module_eval do
|
10
|
+
define_method :test_track_identifier_type do
|
11
|
+
identifier_type
|
12
|
+
end
|
13
|
+
|
14
|
+
define_method :test_track_identifier_value do
|
15
|
+
send(identifier_value_method)
|
16
|
+
end
|
17
|
+
|
11
18
|
define_method :test_track_ab do |*args|
|
12
19
|
discriminator = TestTrack::IdentitySessionDiscriminator.new(self)
|
13
|
-
|
14
|
-
|
15
|
-
discriminator.controller.send(:test_track_visitor).ab(*args)
|
16
|
-
else
|
17
|
-
identifier_value = send(identifier_value_method)
|
18
|
-
TestTrack::OfflineSession.with_visitor_for(identifier_type, identifier_value) do |v|
|
19
|
-
v.ab(*args)
|
20
|
-
end
|
20
|
+
discriminator.with_visitor do |v|
|
21
|
+
v.ab(*args)
|
21
22
|
end
|
22
23
|
end
|
23
24
|
|
24
25
|
define_method :test_track_vary do |*args, &block|
|
25
26
|
discriminator = TestTrack::IdentitySessionDiscriminator.new(self)
|
26
|
-
|
27
|
-
|
28
|
-
discriminator.controller.send(:test_track_visitor).vary(*args, &block)
|
29
|
-
else
|
30
|
-
identifier_value = send(identifier_value_method)
|
31
|
-
TestTrack::OfflineSession.with_visitor_for(identifier_type, identifier_value) do |v|
|
32
|
-
v.vary(*args, &block)
|
33
|
-
end
|
27
|
+
discriminator.with_visitor do |v|
|
28
|
+
v.vary(*args, &block)
|
34
29
|
end
|
35
30
|
end
|
36
31
|
|
37
32
|
define_method :test_track_visitor_id do
|
38
33
|
discriminator = TestTrack::IdentitySessionDiscriminator.new(self)
|
39
|
-
|
40
|
-
|
41
|
-
discriminator.controller.send(:test_track_visitor).id
|
42
|
-
else
|
43
|
-
identifier_value = send(identifier_value_method)
|
44
|
-
TestTrack::OfflineSession.with_visitor_for(identifier_type, identifier_value) do |v|
|
45
|
-
v.id
|
46
|
-
end
|
34
|
+
discriminator.with_visitor do |v|
|
35
|
+
v.id
|
47
36
|
end
|
48
37
|
end
|
49
38
|
|
50
39
|
define_method :test_track_sign_up! do
|
51
40
|
discriminator = TestTrack::IdentitySessionDiscriminator.new(self)
|
52
|
-
|
53
|
-
|
54
|
-
identifier_value = send(identifier_value_method)
|
55
|
-
discriminator.controller.send(:test_track_session).sign_up! identifier_type, identifier_value
|
56
|
-
else
|
57
|
-
raise "test_track_sign_up! called outside of a web context"
|
41
|
+
discriminator.with_session do |session|
|
42
|
+
session.sign_up! self
|
58
43
|
end
|
59
44
|
end
|
60
45
|
|
61
46
|
define_method :test_track_log_in! do |opts = {}|
|
62
47
|
discriminator = TestTrack::IdentitySessionDiscriminator.new(self)
|
63
|
-
|
64
|
-
|
65
|
-
identifier_value = send(identifier_value_method)
|
66
|
-
discriminator.controller.send(:test_track_session).log_in! identifier_type, identifier_value, opts
|
67
|
-
else
|
68
|
-
raise "test_track_log_in! called outside of a web context"
|
48
|
+
discriminator.with_session do |session|
|
49
|
+
session.log_in! self, opts
|
69
50
|
end
|
70
51
|
end
|
71
52
|
end
|
72
53
|
end
|
73
|
-
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize, Metrics/PerceivedComplexity
|
74
54
|
end
|
75
55
|
end
|
@@ -5,26 +5,39 @@ class TestTrack::IdentitySessionDiscriminator
|
|
5
5
|
@identity = identity
|
6
6
|
end
|
7
7
|
|
8
|
-
def
|
9
|
-
|
10
|
-
end
|
8
|
+
def with_visitor
|
9
|
+
raise ArgumentError, "must provide block to `with_visitor`" unless block_given?
|
11
10
|
|
12
|
-
|
13
|
-
|
11
|
+
if matching_identity?
|
12
|
+
yield session.visitor_dsl
|
13
|
+
else
|
14
|
+
TestTrack::OfflineSession.with_visitor_for(identity.test_track_identifier_type, identity.test_track_identifier_value) do |v|
|
15
|
+
yield v
|
16
|
+
end
|
17
|
+
end
|
14
18
|
end
|
15
19
|
|
16
|
-
def
|
17
|
-
|
20
|
+
def with_session
|
21
|
+
raise ArgumentError, "must provide block to `with_session`" unless block_given?
|
22
|
+
|
23
|
+
if web_context?
|
24
|
+
yield session
|
25
|
+
else
|
26
|
+
raise "#with_session called outside of web context"
|
27
|
+
end
|
18
28
|
end
|
19
29
|
|
20
30
|
private
|
21
31
|
|
22
|
-
def
|
23
|
-
|
24
|
-
|
32
|
+
def matching_identity?
|
33
|
+
session.present? && session.has_matching_identity?(identity)
|
34
|
+
end
|
35
|
+
|
36
|
+
def web_context?
|
37
|
+
session.present?
|
25
38
|
end
|
26
39
|
|
27
|
-
def
|
28
|
-
@
|
40
|
+
def session
|
41
|
+
@session ||= RequestStore[:test_track_session]
|
29
42
|
end
|
30
43
|
end
|
@@ -31,18 +31,48 @@ class TestTrack::Session
|
|
31
31
|
}
|
32
32
|
end
|
33
33
|
|
34
|
-
def log_in!(
|
34
|
+
def log_in!(*args) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
35
|
+
opts = args[-1].is_a?(Hash) ? args.pop : {}
|
36
|
+
|
37
|
+
if args[0].is_a?(TestTrack::Identity)
|
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
|
+
|
35
47
|
@visitor = TestTrack::Visitor.new if opts[:forget_current_visitor]
|
36
48
|
visitor.link_identifier!(identifier_type, identifier_value)
|
49
|
+
|
50
|
+
identities << identity if identity.present?
|
37
51
|
self.mixpanel_distinct_id = visitor.id
|
38
52
|
true
|
39
53
|
end
|
40
54
|
|
41
|
-
def sign_up!(
|
55
|
+
def sign_up!(*args) # rubocop:disable Metrics/MethodLength
|
56
|
+
if args[0].is_a?(TestTrack::Identity)
|
57
|
+
identity = args[0]
|
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
|
65
|
+
|
42
66
|
visitor.link_identifier!(identifier_type, identifier_value)
|
67
|
+
|
68
|
+
identities << identity if identity.present?
|
43
69
|
@signed_up = true
|
44
70
|
end
|
45
71
|
|
72
|
+
def has_matching_identity?(identity)
|
73
|
+
identities.include?(identity)
|
74
|
+
end
|
75
|
+
|
46
76
|
private
|
47
77
|
|
48
78
|
attr_reader :controller, :signed_up
|
@@ -215,4 +245,8 @@ class TestTrack::Session
|
|
215
245
|
end
|
216
246
|
end
|
217
247
|
end
|
248
|
+
|
249
|
+
def identities
|
250
|
+
@identities ||= TestTrack::SessionIdentityCollection.new(controller)
|
251
|
+
end
|
218
252
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class TestTrack::SessionIdentityCollection
|
2
|
+
def initialize(controller)
|
3
|
+
@controller = controller
|
4
|
+
end
|
5
|
+
|
6
|
+
def include?(identity)
|
7
|
+
found_identity = identities[identity.test_track_identifier_type] || authenticated_resource_for_identity(identity)
|
8
|
+
found_identity.present? && found_identity == identity
|
9
|
+
end
|
10
|
+
|
11
|
+
def <<(identity)
|
12
|
+
identities[identity.test_track_identifier_type] = identity
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
attr_reader :controller
|
18
|
+
|
19
|
+
def identities
|
20
|
+
@identities ||= {}
|
21
|
+
end
|
22
|
+
|
23
|
+
def authenticated_resource_for_identity(identity)
|
24
|
+
authenticated_resource_method_name = "current_#{identity.class.model_name.element}"
|
25
|
+
|
26
|
+
# pass true to `respond_to?` to include private methods
|
27
|
+
controller.respond_to?(authenticated_resource_method_name, true) && controller.send(authenticated_resource_method_name)
|
28
|
+
end
|
29
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: test_track_rails_client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan O'Neill
|
@@ -13,7 +13,7 @@ authors:
|
|
13
13
|
autorequire:
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
|
-
date: 2017-
|
16
|
+
date: 2017-10-02 00:00:00.000000000 Z
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
19
19
|
name: rails
|
@@ -291,6 +291,7 @@ files:
|
|
291
291
|
- app/models/test_track/remote/visitor.rb
|
292
292
|
- app/models/test_track/remote/visitor_detail.rb
|
293
293
|
- app/models/test_track/session.rb
|
294
|
+
- app/models/test_track/session_identity_collection.rb
|
294
295
|
- app/models/test_track/unsynced_assignments_notifier.rb
|
295
296
|
- app/models/test_track/variant_calculator.rb
|
296
297
|
- app/models/test_track/vary_dsl.rb
|
@@ -441,7 +442,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
441
442
|
version: '0'
|
442
443
|
requirements: []
|
443
444
|
rubyforge_project:
|
444
|
-
rubygems_version: 2.
|
445
|
+
rubygems_version: 2.6.13
|
445
446
|
signing_key:
|
446
447
|
specification_version: 4
|
447
448
|
summary: Rails client for TestTrack
|