Module: Split::Helper

Included in:
EncapsulatedHelper::ContextShim
Defined in:
lib/split/helper.rb

Constant Summary collapse

OVERRIDE_PARAM_NAME =
"ab_test"

Class Method Summary collapse

Class Method Details

.ab_finished(metric_descriptor, options = {:reset => true}) ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/split/helper.rb', line 64

def ab_finished(metric_descriptor, options = {:reset => true})
  return if exclude_visitor? || Split.configuration.disabled?
  metric_descriptor, goals = normalize_metric(metric_descriptor)
  experiments = Metric.possible_experiments(metric_descriptor)

  if experiments.any?
    experiments.each do |experiment|
      finish_experiment(experiment, options.merge(:goals => goals))
    end
  end
rescue => e
  raise unless Split.configuration.db_failover
  Split.configuration.db_failover_on_db_error.call(e)
end

.ab_record_extra_info(metric_descriptor, key, value = 1) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/split/helper.rb', line 79

def ab_record_extra_info(metric_descriptor, key, value = 1)
  return if exclude_visitor? || Split.configuration.disabled?
  metric_descriptor, goals = normalize_metric(metric_descriptor)
  experiments = Metric.possible_experiments(metric_descriptor)

  if experiments.any?
    experiments.each do |experiment|
      alternative_name = ab_user[experiment.key]

      if alternative_name
        alternative = experiment.alternatives.find{|alt| alt.name == alternative_name}
        alternative.record_extra_info(key, value) if alternative
      end
    end
  end
rescue => e
  raise unless Split.configuration.db_failover
  Split.configuration.db_failover_on_db_error.call(e)
end

.ab_test(metric_descriptor, control = nil, *alternatives) ⇒ Object



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/split/helper.rb', line 8

def ab_test(metric_descriptor, control = nil, *alternatives)
  begin
    experiment = ExperimentCatalog.find_or_initialize(metric_descriptor, control, *alternatives)
    alternative = if Split.configuration.enabled
      experiment.save
      trial = Trial.new(:user => ab_user, :experiment => experiment,
          :override => override_alternative(experiment.name), :exclude => exclude_visitor?,
          :disabled => split_generically_disabled?)
      alt = trial.choose!(self)
      alt ? alt.name : nil
    else
      control_variable(experiment.control)
    end
  rescue Errno::ECONNREFUSED, Redis::BaseError, SocketError => e
    raise(e) unless Split.configuration.db_failover
    Split.configuration.db_failover_on_db_error.call(e)

    if Split.configuration.db_failover_allow_parameter_override
      alternative = override_alternative(experiment.name) if override_present?(experiment.name)
      alternative = control_variable(experiment.control) if split_generically_disabled?
    end
  ensure
    alternative ||= control_variable(experiment.control)
  end

  if block_given?
     = trial ? trial. : {}
    yield(alternative, )
  else
    alternative
  end
end

.ab_userObject



111
112
113
# File 'lib/split/helper.rb', line 111

def ab_user
  @ab_user ||= User.new(self)
end

.active_experimentsObject



132
133
134
# File 'lib/split/helper.rb', line 132

def active_experiments
  ab_user.active_experiments
end

.control_variable(control) ⇒ Object



147
148
149
# File 'lib/split/helper.rb', line 147

def control_variable(control)
  Hash === control ? control.keys.first.to_s : control.to_s
end

.exclude_visitor?Boolean

Returns:

  • (Boolean)


115
116
117
# File 'lib/split/helper.rb', line 115

def exclude_visitor?
  instance_eval(&Split.configuration.ignore_filter) || is_ignored_ip_address? || is_robot?
end

.finish_experiment(experiment, options = {:reset => true}) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/split/helper.rb', line 45

def finish_experiment(experiment, options = {:reset => true})
  return true if experiment.has_winner?
  should_reset = experiment.resettable? && options[:reset]
  if ab_user[experiment.finished_key] && !should_reset
    return true
  else
    alternative_name = ab_user[experiment.key]
    trial = Trial.new(:user => ab_user, :experiment => experiment,
          :alternative => alternative_name)
    trial.complete!(options[:goals], self)

    if should_reset
      reset!(experiment)
    else
      ab_user[experiment.finished_key] = true
    end
  end
end

.is_ignored_ip_address?Boolean

Returns:

  • (Boolean)


123
124
125
126
127
128
129
130
# File 'lib/split/helper.rb', line 123

def is_ignored_ip_address?
  return false if Split.configuration.ignore_ip_addresses.empty?

  Split.configuration.ignore_ip_addresses.each do |ip|
    return true if defined?(request) && (request.ip == ip || (ip.class == Regexp && request.ip =~ ip))
  end
  false
end

.is_robot?Boolean

Returns:

  • (Boolean)


119
120
121
# File 'lib/split/helper.rb', line 119

def is_robot?
  defined?(request) && request.user_agent =~ Split.configuration.robot_regex
end

.normalize_metric(metric_descriptor) ⇒ Object



136
137
138
139
140
141
142
143
144
145
# File 'lib/split/helper.rb', line 136

def normalize_metric(metric_descriptor)
  if Hash === metric_descriptor
    experiment_name = metric_descriptor.keys.first
    goals = Array(metric_descriptor.values.first)
  else
    experiment_name = metric_descriptor
    goals = []
  end
  return experiment_name, goals
end

.override_alternative(experiment_name) ⇒ Object



103
104
105
# File 'lib/split/helper.rb', line 103

def override_alternative(experiment_name)
  defined?(params) && params[OVERRIDE_PARAM_NAME] && params[OVERRIDE_PARAM_NAME][experiment_name]
end

.override_present?(experiment_name) ⇒ Boolean

Returns:

  • (Boolean)


99
100
101
# File 'lib/split/helper.rb', line 99

def override_present?(experiment_name)
  override_alternative(experiment_name)
end

.reset!(experiment) ⇒ Object



41
42
43
# File 'lib/split/helper.rb', line 41

def reset!(experiment)
  ab_user.delete(experiment.key)
end

.split_generically_disabled?Boolean

Returns:

  • (Boolean)


107
108
109
# File 'lib/split/helper.rb', line 107

def split_generically_disabled?
  defined?(params) && params['SPLIT_DISABLE']
end