test_track_rails_client 4.0.0.alpha7 → 4.0.0.alpha8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 783a76b4acdaebee2ff453ba5513d49e804c985c
4
- data.tar.gz: 4f36e75ebc4a144a02daf0fcd3d53d48deb8bcc2
3
+ metadata.gz: 3c421a570a50e10dbfdff7420aafa19964ee4c01
4
+ data.tar.gz: 901a202cbb0db2717ba240b6466f6408ddb1b3c4
5
5
  SHA512:
6
- metadata.gz: 7725742abb3fa4099ef8e2c4571b820a8b28bb987f0d6e7b111d92c1e7f5de5049311a69217ca576ba56c947cacbeb97966d077c930a4b8a1d17576f7e4bcaf1
7
- data.tar.gz: 3155aa14210aca6d48bd44c02a7e71be22d0dac81bc6472c9299459e8969527346ae9f98dd0fe7d3e909ba6acb4aec2b7345868b4d318cea1f3947f05c0a4ab2
6
+ metadata.gz: 684fa6562e8a88bd4092bbd2cf0f5527f84c4c4e55b307c5ca9ec88f4d965cfb193aec37fb20a08aefda96588fbc34597f9b1b91198bf3390c3dde7c09484505
7
+ data.tar.gz: 63edb85ee37e5eba3d15fc2f926eca2aae470bf0f927d2b5cde366206edc48f8b12ebc685849343fd06fb66a54a53aa101e51606e02c4869923bad91694c750c
data/README.md CHANGED
@@ -21,13 +21,15 @@ If you're looking to do client-side assignment, then check out our [JS client](h
21
21
 
22
22
  ## Installation
23
23
 
24
- Install the gem:
24
+ ### Install the gem:
25
25
 
26
26
  ```ruby
27
27
  # Gemfile
28
28
  gem 'test_track_rails_client'
29
29
  ```
30
30
 
31
+ ### Create an app in the TestTrack server
32
+
31
33
  In every environment (local included) cut an App record via the **TestTrack server** rails console:
32
34
 
33
35
  ```ruby
@@ -40,6 +42,8 @@ README](https://github.com/Betterment/test_track/blob/master/README.md#user-cont
40
42
  for additional information on configuring seed apps for local
41
43
  development.
42
44
 
45
+ ### Set up ENV vars
46
+
43
47
  Set up ENV vars in every environment:
44
48
 
45
49
  * `MIXPANEL_TOKEN` - By default, TestTrack reports to Mixpanel. If you're using a [custom analytics provider](#custom-analytics) you can omit this.
@@ -51,15 +55,28 @@ Set up ENV vars in every environment:
51
55
  * `example.org`
52
56
  * etc
53
57
 
58
+ ### Prepare your controllers
54
59
 
55
- Mix `TestTrack::Controller` into any controllers needing access to TestTrack:
60
+ Mix `TestTrack::Controller` into any controllers needing access to TestTrack and configure it with the name of your `:current_user` method.
56
61
 
57
62
  ```ruby
58
63
  class MyController < ApplicationController
59
64
  include TestTrack::Controller
65
+
66
+ self.test_track_identity = :current_user
60
67
  end
61
68
  ```
62
69
 
70
+ If your app doesn't support authentication, set
71
+ `self.test_track_identity` to `:none`.
72
+
73
+ ### Prepare your identity models (optional)
74
+
75
+ If your app supports authentication, You'll need to configure your
76
+ `User` model as a [TestTrack Identity](#varying-app-behavior-from-within-a-model)
77
+
78
+ ### Set up the Chrome extension (optional)
79
+
63
80
  If you'd like to be able to use the [TestTrack Chrome Extension](https://github.com/Betterment/test_track_chrome_extension) which makes it easy for you and your team to change assignments via your browser, you **must** set up the TestTrack JS client.
64
81
 
65
82
  1. `testTrack.bundle.min` in your `application.js` file after your reference to jQuery
@@ -239,51 +256,9 @@ if test_track_visitor.ab :dark_deployed_feature, context: 'signup'
239
256
  end
240
257
  ```
241
258
 
242
- ### Varying app behavior in an offline context
243
-
244
- The `OfflineSession` class can be used to load a test track visitor when there is no access to browser cookies. It is perfect for use in a process being run from either a job queue or a scheduler. The visitor object that is yielded to the block is the same as the visitor in a controller context; it has both the `vary` and `ab` methods.
245
-
246
- An `OfflineSession` can be established in one of two ways:
247
-
248
- 1. with an `identifier_type`:
249
- ```ruby
250
- OfflineSession.with_visitor_for(:myapp_user_id, 1234) do |test_track_visitor|
251
- test_track_visitor.vary :name_of_split, context: 'background_job' do |v|
252
- v.when :variant_1, :variant_2 do
253
- # Do something
254
- end
255
- v.when :variant_3 do
256
- # Do another thing
257
- end
258
- v.default :variant_4 do
259
- # Do something else
260
- end
261
- end
262
- end
263
- ```
264
-
265
- 2. with a `TestTrack::Visitor#id`:
266
- ```ruby
267
- OfflineSession.with_visitor_id(1234) do |test_track_visitor|
268
- test_track_visitor.vary :name_of_split, context: 'background_job' do |v|
269
- v.when :variant_1, :variant_2 do
270
- # Do something
271
- end
272
- v.when :variant_3 do
273
- # Do another thing
274
- end
275
- v.default :variant_4 do
276
- # Do something else
277
- end
278
- end
279
- end
280
- ```
281
-
282
259
  ### Varying app behavior from within a model
283
260
 
284
- The `TestTrack::Identity` concern can be included in a model and it will add two methods to the model: `test_track_vary` and `test_track_ab`. Behind the scenes, these methods check to see if they are being used within a web context of a controller that includes `TestTrack::Controller` or not. If called in a web context they will use the `test_track_visitor` that the controller has and participate in the existing session, if not, they will standup an `OfflineSession`.
285
-
286
- Because these methods may need to stand up an `OfflineSession` the consuming model needs to provide both the identifier type and which column should be used as the identifier value via the `test_track_identifier` method so that the `OfflineSession` can grab the correct visitor.
261
+ The `TestTrack::Identity` concern can be included in a model and it will add two methods to the model: `test_track_vary` and `test_track_ab`.
287
262
 
288
263
  ```ruby
289
264
  class User
@@ -293,8 +268,6 @@ class User
293
268
  end
294
269
  ```
295
270
 
296
- N.B. If you call `test_track_vary` and `test_track_ab` on a model in a web context, but that model is not the currently authenticated model, an `OfflineSession` will be created instead of participating in the existing session.
297
-
298
271
  ## Tracking visitor logins
299
272
 
300
273
  The `test_track_visitor.log_in!` is used to ensure a consistent experience across devices. For instance, when a user logs in to your app on their mobile device we can log in to Test Track in order to grab their existing split assignments instead of treating them like a new visitor.
@@ -317,7 +290,7 @@ The `test_track_visitor.sign_up!` method tells TestTrack when a new identifier h
317
290
  test_track_visitor.sign_up!(:myapp_user_id, 2345)
318
291
  ```
319
292
 
320
- ## Testing splits
293
+ ## Testing your split-dependent application code with RSpec
321
294
 
322
295
  Add this line to your `rails_helper.rb`:
323
296
 
@@ -384,6 +357,14 @@ easier and more conventional, though, and takes care of differentiating
384
357
  between expiriment assignments and feature gate experiences, which are
385
358
  no longer recorded server-side.
386
359
 
360
+ You also must add `self.test_track_identity = :current_user` (or
361
+ whatever your controller uses as a sign-in identity) to your
362
+ TestTrack-enabled controllers, or set it to `:none` if your app doesn't
363
+ support authentication.
364
+
365
+ If your app supports authentication, You'll need to configure your
366
+ user model as a [TestTrack Identity](#varying-app-behavior-from-within-a-model)
367
+
387
368
  ### From 2.0 to 3.0
388
369
 
389
370
  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.
@@ -2,6 +2,8 @@ module TestTrack::Controller
2
2
  extend ActiveSupport::Concern
3
3
 
4
4
  included do
5
+ class_attribute :test_track_identity
6
+
5
7
  helper_method :test_track_session, :test_track_visitor
6
8
  helper TestTrack::ApplicationHelper
7
9
  around_action :manage_test_track_session
@@ -19,7 +19,9 @@ class TestTrack::ABConfiguration
19
19
  private
20
20
 
21
21
  def build_variant_hash
22
- notify_because_ab("configures split with more than 2 variants") if split_variants && split_variants.size > 2
22
+ if split_variants && split_variants.size > 2 # rubocop:disable Style/SafeNavigation
23
+ notify_because_ab("configures split with more than 2 variants")
24
+ end
23
25
  { true: true_variant, false: false_variant }
24
26
  end
25
27
 
@@ -0,0 +1,38 @@
1
+ class TestTrack::LazyVisitorByIdentity
2
+ def initialize(identity)
3
+ @identity = identity
4
+ end
5
+
6
+ def loaded?
7
+ @visitor.present?
8
+ end
9
+
10
+ def id_loaded?
11
+ loaded?
12
+ end
13
+
14
+ private
15
+
16
+ def method_missing(method, *args, &block) # rubocop:disable Style/MethodMissing
17
+ __visitor__.send(method, *args, &block)
18
+ end
19
+
20
+ def respond_to_missing?(method, include_private = false)
21
+ super || __visitor__.respond_to?(method, include_private)
22
+ end
23
+
24
+ def __visitor__
25
+ @visitor ||= __load_visitor__
26
+ end
27
+
28
+ def __load_visitor__
29
+ remote_visitor = TestTrack::Remote::Visitor.from_identifier(
30
+ @identity.test_track_identifier_type,
31
+ @identity.test_track_identifier_value
32
+ )
33
+ TestTrack::Visitor.new(
34
+ id: remote_visitor.id,
35
+ assignments: remote_visitor.assignments
36
+ )
37
+ end
38
+ end
@@ -11,34 +11,19 @@ class TestTrack::Session
11
11
  def manage
12
12
  yield
13
13
  ensure
14
- manage_cookies!
15
- manage_response_headers!
16
- notify_unsynced_assignments! if sync_assignments?
17
- end
18
-
19
- def visitor_dsl_for(identity)
20
- if has_matching_identity?(identity)
21
- visitor_dsl
22
- else
23
- TestTrack::VisitorDSL.new(visitors_by_identity[identity])
14
+ if current_visitor.id_loaded?
15
+ manage_cookies!
16
+ manage_response_headers!
24
17
  end
18
+ visitors.notify_unsynced_assignments!
25
19
  end
26
20
 
27
- def visitors_by_identity
28
- @visitors_by_identity ||= Hash.new do |visitors_by_identity, identity|
29
- remote_visitor = TestTrack::Remote::Visitor.from_identifier(
30
- identity.test_track_identifier_type,
31
- identity.test_track_identifier_value
32
- )
33
- visitors_by_identity[identity] = TestTrack::Visitor.new(
34
- id: remote_visitor.id,
35
- assignments: remote_visitor.assignments
36
- )
37
- end
21
+ def visitor_dsl_for(identity)
22
+ TestTrack::VisitorDSL.new(visitors.for_identity(identity))
38
23
  end
39
24
 
40
25
  def visitor_dsl
41
- @visitor_dsl ||= TestTrack::VisitorDSL.new(visitor)
26
+ TestTrack::VisitorDSL.new(current_visitor)
42
27
  end
43
28
 
44
29
  def state_hash
@@ -46,50 +31,55 @@ class TestTrack::Session
46
31
  url: TestTrack.url,
47
32
  cookieDomain: cookie_domain,
48
33
  cookieName: visitor_cookie_name,
49
- registry: visitor.split_registry,
50
- assignments: visitor.assignment_json
34
+ registry: current_visitor.split_registry,
35
+ assignments: current_visitor.assignment_json
51
36
  }
52
37
  end
53
38
 
54
39
  def log_in!(identity, forget_current_visitor: nil)
55
- identifier_type = identity.test_track_identifier_type
56
- identifier_value = identity.test_track_identifier_value
57
-
58
- @visitor = TestTrack::Visitor.new if forget_current_visitor
59
- visitor.link_identifier!(identifier_type, identifier_value)
60
-
61
- identities << identity if identity.present?
40
+ visitors.forget_unauthenticated! if forget_current_visitor
41
+ visitors.authenticate!(identity)
62
42
  true
63
43
  end
64
44
 
65
45
  def sign_up!(identity)
66
- identifier_type = identity.test_track_identifier_type
67
- identifier_value = identity.test_track_identifier_value
68
-
69
- visitor.link_identifier!(identifier_type, identifier_value)
70
- identities << identity if identity.present?
71
-
72
- TestTrack.analytics.sign_up!(visitor.id)
73
-
46
+ visitors.authenticate!(identity)
47
+ TestTrack.analytics.sign_up!(current_visitor.id)
74
48
  true
75
49
  end
76
50
 
77
- def has_matching_identity?(identity)
78
- identities.include?(identity)
79
- end
80
-
81
51
  private
82
52
 
83
53
  attr_reader :controller
84
54
 
85
- def visitor
86
- @visitor ||= TestTrack::Visitor.new(id: visitor_id)
55
+ def current_identity
56
+ raise <<~ERROR unless controller.class.test_track_identity&.is_a?(Symbol)
57
+ Your controller (or controller base class) must set test_track_identity for
58
+ TestTrack to work properly. e.g.:
59
+
60
+ self.test_track_identity = :current_user
61
+
62
+ If your app doesn't support authentication, set it to `:none`.
63
+ ERROR
64
+ identity = controller.class.test_track_identity
65
+ controller.send(identity) unless identity == :none
87
66
  end
88
67
 
89
- def visitor_id
68
+ def unauthenticated_visitor_id
90
69
  cookies[visitor_cookie_name] || request_headers[visitor_request_header_name]
91
70
  end
92
71
 
72
+ def visitors
73
+ @visitors ||= TestTrack::SessionVisitorRepository.new(
74
+ current_identity: current_identity,
75
+ unauthenticated_visitor_id: unauthenticated_visitor_id
76
+ )
77
+ end
78
+
79
+ def current_visitor
80
+ visitors.current
81
+ end
82
+
93
83
  def set_cookie(name, value)
94
84
  cookies[name] = {
95
85
  value: value,
@@ -131,7 +121,7 @@ class TestTrack::Session
131
121
  end
132
122
 
133
123
  def manage_cookies!
134
- set_cookie(visitor_cookie_name, visitor.id)
124
+ set_cookie(visitor_cookie_name, current_visitor.id)
135
125
  end
136
126
 
137
127
  def request
@@ -155,26 +145,7 @@ class TestTrack::Session
155
145
  end
156
146
 
157
147
  def manage_response_headers!
158
- response_headers[visitor_response_header_name] = visitor.id if visitor.id_overridden_by_existing_visitor?
159
- end
160
-
161
- def notify_unsynced_assignments!
162
- payload = {
163
- visitor_id: visitor.id,
164
- assignments: visitor.unsynced_assignments
165
- }
166
- ActiveSupport::Notifications.instrument('test_track.notify_unsynced_assignments', payload) do
167
- ##
168
- # This block creates an unbounded number of threads up to 1 per request.
169
- # This can potentially cause issues under high load, in which case we should move to a thread pool/work queue.
170
- new_thread_with_request_store do
171
- TestTrack::UnsyncedAssignmentsNotifier.new(payload).notify
172
- end
173
- end
174
- end
175
-
176
- def sync_assignments?
177
- visitor.loaded? && visitor.unsynced_assignments.present?
148
+ response_headers[visitor_response_header_name] = current_visitor.id if current_visitor.id_overridden_by_existing_visitor?
178
149
  end
179
150
 
180
151
  def visitor_cookie_name
@@ -192,21 +163,4 @@ class TestTrack::Session
192
163
  def fully_qualified_cookie_domain_enabled?
193
164
  ENV['TEST_TRACK_FULLY_QUALIFIED_COOKIE_DOMAIN_ENABLED'] == '1'
194
165
  end
195
-
196
- def new_thread_with_request_store
197
- Thread.new(RequestStore.store) do |original_store|
198
- begin
199
- RequestStore.begin!
200
- RequestStore.store.merge!(original_store)
201
- yield
202
- ensure
203
- RequestStore.end!
204
- RequestStore.clear!
205
- end
206
- end
207
- end
208
-
209
- def identities
210
- @identities ||= TestTrack::SessionIdentityCollection.new(controller)
211
- end
212
166
  end
@@ -0,0 +1,52 @@
1
+ class TestTrack::SessionVisitorRepository
2
+ attr_reader :current_identity, :unauthenticated_visitor_id
3
+
4
+ def initialize(current_identity:, unauthenticated_visitor_id:)
5
+ @current_identity = current_identity
6
+ @unauthenticated_visitor_id = unauthenticated_visitor_id
7
+ end
8
+
9
+ def current
10
+ if current_identity
11
+ for_identity(current_identity)
12
+ else
13
+ unauthenticated
14
+ end
15
+ end
16
+
17
+ def for_identity(identity)
18
+ identity_visitor_map[identity] ||= TestTrack::LazyVisitorByIdentity.new(identity)
19
+ end
20
+
21
+ def forget_unauthenticated!
22
+ @unauthenticated = TestTrack::Visitor.new
23
+ end
24
+
25
+ def authenticate!(identity)
26
+ @current_identity = identity
27
+ identity_visitor_map[identity] = unauthenticated
28
+ unauthenticated.link_identity!(identity)
29
+ end
30
+
31
+ def all
32
+ identity_visitor_map.values.to_set << current
33
+ end
34
+
35
+ def notify_unsynced_assignments!
36
+ all.each do |visitor|
37
+ if visitor.loaded? && visitor.unsynced_assignments.present?
38
+ TestTrack::ThreadedVisitorNotifier.new(visitor).notify
39
+ end
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def unauthenticated
46
+ @unauthenticated ||= TestTrack::Visitor.new(id: unauthenticated_visitor_id)
47
+ end
48
+
49
+ def identity_visitor_map
50
+ @identity_visitor_map ||= {}
51
+ end
52
+ end
@@ -0,0 +1,34 @@
1
+ class TestTrack::ThreadedVisitorNotifier
2
+ attr_reader :visitor
3
+
4
+ def initialize(visitor)
5
+ @visitor = visitor
6
+ end
7
+
8
+ def notify
9
+ payload = {
10
+ visitor_id: visitor.id,
11
+ assignments: visitor.unsynced_assignments
12
+ }
13
+ ActiveSupport::Notifications.instrument('test_track.notify_unsynced_assignments', payload) do
14
+ new_thread_with_request_store do
15
+ TestTrack::UnsyncedAssignmentsNotifier.new(payload).notify
16
+ end
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def new_thread_with_request_store
23
+ Thread.new(RequestStore.store) do |original_store|
24
+ begin
25
+ RequestStore.begin!
26
+ RequestStore.store.merge!(original_store)
27
+ yield
28
+ ensure
29
+ RequestStore.end!
30
+ RequestStore.clear!
31
+ end
32
+ end
33
+ end
34
+ end
@@ -6,6 +6,7 @@ class TestTrack::Visitor
6
6
  def initialize(opts = {})
7
7
  opts = opts.dup
8
8
  @id = opts.delete(:id)
9
+ @loaded = true if opts[:assignments]
9
10
  @assignments = opts.delete(:assignments)
10
11
  unless id
11
12
  @id = SecureRandom.uuid
@@ -65,17 +66,17 @@ class TestTrack::Visitor
65
66
  @split_registry ||= TestTrack::Remote::SplitRegistry.to_hash
66
67
  end
67
68
 
68
- def link_identifier!(identifier_type, identifier_value)
69
- identifier_opts = { identifier_type: identifier_type, visitor_id: id, value: identifier_value.to_s }
69
+ def link_identity!(identity)
70
+ opts = identifier_opts(identity)
70
71
  begin
71
- identifier = TestTrack::Remote::Identifier.create!(identifier_opts)
72
+ identifier = TestTrack::Remote::Identifier.create!(opts)
72
73
  merge!(identifier.visitor)
73
74
  rescue *TestTrack::SERVER_ERRORS => e
74
75
  Rails.logger.error "TestTrack failed to link identifier, retrying. #{e}"
75
76
 
76
77
  # If at first you don't succeed, async it - we may not display 100% consistent UX this time,
77
78
  # but subsequent requests will be better off
78
- TestTrack::Remote::Identifier.delay.create!(identifier_opts)
79
+ TestTrack::Remote::Identifier.delay.create!(opts)
79
80
  end
80
81
  end
81
82
 
@@ -83,8 +84,12 @@ class TestTrack::Visitor
83
84
  @tt_offline
84
85
  end
85
86
 
87
+ def id_loaded?
88
+ true
89
+ end
90
+
86
91
  def loaded?
87
- !offline? && @remote_visitor.present?
92
+ !offline? && @loaded
88
93
  end
89
94
 
90
95
  def id_overridden_by_existing_visitor?
@@ -93,12 +98,28 @@ class TestTrack::Visitor
93
98
 
94
99
  private
95
100
 
101
+ def identifier_opts(identity)
102
+ {
103
+ identifier_type: identity.test_track_identifier_type,
104
+ visitor_id: id,
105
+ value: identity.test_track_identifier_value.to_s
106
+ }
107
+ end
108
+
96
109
  def assignments
97
- @assignments ||= (remote_visitor && remote_visitor.assignments) || []
110
+ @assignments ||= remote_visitor&.assignments || []
98
111
  end
99
112
 
100
113
  def remote_visitor
101
- @remote_visitor ||= TestTrack::Remote::Visitor.find(id) unless tt_offline?
114
+ @remote_visitor ||= _remote_visitor
115
+ end
116
+
117
+ def _remote_visitor
118
+ unless tt_offline?
119
+ TestTrack::Remote::Visitor.find(id).tap do |_|
120
+ @loaded = true
121
+ end
122
+ end
102
123
  rescue *TestTrack::SERVER_ERRORS => e
103
124
  Rails.logger.error "TestTrack failed to load remote visitor. #{e}"
104
125
  @tt_offline = true
@@ -1,3 +1,3 @@
1
1
  module TestTrackRailsClient
2
- VERSION = "4.0.0.alpha7" # rubocop:disable Style/MutableConstant
2
+ VERSION = "4.0.0.alpha8" # rubocop:disable Style/MutableConstant
3
3
  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: 4.0.0.alpha7
4
+ version: 4.0.0.alpha8
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: 2018-05-01 00:00:00.000000000 Z
16
+ date: 2018-05-08 00:00:00.000000000 Z
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
19
19
  name: airbrake
@@ -268,6 +268,7 @@ files:
268
268
  - app/models/test_track/fake/visitor_detail.rb
269
269
  - app/models/test_track/fake_server.rb
270
270
  - app/models/test_track/identity_session_locator.rb
271
+ - app/models/test_track/lazy_visitor_by_identity.rb
271
272
  - app/models/test_track/misconfiguration_notifier.rb
272
273
  - app/models/test_track/notify_assignment_job.rb
273
274
  - app/models/test_track/offline_session.rb
@@ -283,7 +284,8 @@ files:
283
284
  - app/models/test_track/remote/visitor.rb
284
285
  - app/models/test_track/remote/visitor_detail.rb
285
286
  - app/models/test_track/session.rb
286
- - app/models/test_track/session_identity_collection.rb
287
+ - app/models/test_track/session_visitor_repository.rb
288
+ - app/models/test_track/threaded_visitor_notifier.rb
287
289
  - app/models/test_track/unsynced_assignments_notifier.rb
288
290
  - app/models/test_track/variant_calculator.rb
289
291
  - app/models/test_track/vary_dsl.rb
@@ -1,29 +0,0 @@
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