Class: TestTrack::Visitor

Inherits:
Object
  • Object
show all
Includes:
RequiredOptions
Defined in:
app/models/test_track/visitor.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts = {}) ⇒ Visitor

Returns a new instance of Visitor.



6
7
8
9
10
11
12
13
14
15
16
# File 'app/models/test_track/visitor.rb', line 6

def initialize(opts = {})
  opts = opts.dup
  @id = opts.delete(:id)
  @loaded = true if opts[:assignments]
  @assignments = opts.delete(:assignments)
  unless id
    @id = SecureRandom.uuid
    @assignments ||= [] # If we're generating a visitor, we don't need to fetch the assignments
  end
  raise "unknown opts: #{opts.keys.to_sentence}" if opts.present?
end

Instance Attribute Details

#idObject (readonly)

Returns the value of attribute id.



4
5
6
# File 'app/models/test_track/visitor.rb', line 4

def id
  @id
end

Instance Method Details

#ab(split_name, opts = {}) ⇒ Object

rubocop:disable Metrics/MethodLength, Metrics/AbcSize



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'app/models/test_track/visitor.rb', line 32

def ab(split_name, opts = {}) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
  opts = opts.dup
  split_name = maybe_prefix(split_name)
  true_variant = opts.delete(:true_variant)
  context = require_option!(opts, :context)
  raise "unknown opts: #{opts.keys.to_sentence}" if opts.present?

  ab_configuration = TestTrack::AbConfiguration.new split_name: split_name, true_variant: true_variant, split_registry: split_registry

  vary(split_name, context: context) do |v|
    v.when ab_configuration.variants[:true] do # rubocop:disable Lint/BooleanSymbol
      true
    end
    v.default ab_configuration.variants[:false] do # rubocop:disable Lint/BooleanSymbol
      false
    end
  end
end

#assignment_jsonObject



61
62
63
64
65
# File 'app/models/test_track/visitor.rb', line 61

def assignment_json
  assignment_registry.values.each_with_object({}) do |assignment, hsh|
    hsh[assignment.split_name] = assignment.variant
  end
end

#assignment_registryObject



51
52
53
54
55
# File 'app/models/test_track/visitor.rb', line 51

def assignment_registry
  @assignment_registry ||= assignments.index_by do |assignment|
    assignment.split_name
  end
end

#id_loaded?Boolean

Returns:

  • (Boolean)


89
90
91
# File 'app/models/test_track/visitor.rb', line 89

def id_loaded?
  true
end

#id_overridden_by_existing_visitor?Boolean

Returns:

  • (Boolean)


97
98
99
# File 'app/models/test_track/visitor.rb', line 97

def id_overridden_by_existing_visitor?
  @id_overridden_by_existing_visitor || false
end


71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'app/models/test_track/visitor.rb', line 71

def link_identity!(identity)
  opts = identifier_opts(identity)
  begin
    identifier = TestTrack::Remote::Identifier.create!(opts)
    merge!(identifier.visitor)
  rescue *TestTrack::SERVER_ERRORS => e
    Rails.logger.error "TestTrack failed to link identifier, retrying. #{e}"

    # If at first you don't succeed, async it - we may not display 100% consistent UX this time,
    # but subsequent requests will be better off
    TestTrack::IdentifierCreationJob.perform_later(opts)
  end
end

#loaded?Boolean

Returns:

  • (Boolean)


93
94
95
# File 'app/models/test_track/visitor.rb', line 93

def loaded?
  !offline? && @loaded
end

#offline?Boolean

Returns:

  • (Boolean)


85
86
87
# File 'app/models/test_track/visitor.rb', line 85

def offline?
  @tt_offline
end

#split_registryObject



67
68
69
# File 'app/models/test_track/visitor.rb', line 67

def split_registry
  @split_registry ||= TestTrack::SplitRegistry.from_remote
end

#unsynced_assignmentsObject



57
58
59
# File 'app/models/test_track/visitor.rb', line 57

def unsynced_assignments
  @unsynced_assignments ||= assignment_registry.values.select(&:unsynced?)
end

#vary(split_name, opts = {}) {|v| ... } ⇒ Object

Yields:

  • (v)

Raises:

  • (ArgumentError)


18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'app/models/test_track/visitor.rb', line 18

def vary(split_name, opts = {})
  opts = opts.dup
  split_name = maybe_prefix(split_name)
  split_name = split_name.to_s
  context = require_option!(opts, :context)
  raise "unknown opts: #{opts.keys.to_sentence}" if opts.present?

  raise ArgumentError, "must provide block to `vary` for #{split_name}" unless block_given?

  v = TestTrack::VaryDsl.new(assignment: assignment_for(split_name), context: context, split_registry: split_registry)
  yield v
  v.send :run
end