Module: Split::Helper

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

Instance Method Summary collapse

Instance Method Details

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



4
5
6
7
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
40
41
# File 'lib/split/helper.rb', line 4

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::CannotConnectError => 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?
    if defined?(capture) # a block in a rails view
      block = Proc.new { yield(alternative) }
      concat(capture(alternative, &block))
      false
    else
      yield(alternative)
    end
  else
    alternative
  end
end

#ab_userObject



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

def ab_user
  @ab_user ||= Split::Persistence.adapter.new(self)
end

#active_experimentsObject



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

def active_experiments
  experiment_pairs = {}
  ab_user.keys.each do |key|
    Metric.possible_experiments(key).each do |experiment|
      if !experiment.has_winner?
        experiment_pairs[key] = ab_user[key]
      end
    end
  end
  return experiment_pairs
end

#begin_experiment(experiment, alternative_name = nil) ⇒ Object



94
95
96
97
98
# File 'lib/split/helper.rb', line 94

def begin_experiment(experiment, alternative_name = nil)
  alternative_name ||= experiment.control.name
  ab_user[experiment.key] = alternative_name
  alternative_name
end

#exclude_visitor?Boolean

Returns:

  • (Boolean)


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

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

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



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

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

#finished(metric_descriptor, options = {:reset => true}) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/split/helper.rb', line 67

def 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

#is_ignored_ip_address?Boolean

Returns:

  • (Boolean)


112
113
114
115
116
117
118
119
# File 'lib/split/helper.rb', line 112

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)


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

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

#override_alternative(experiment_name) ⇒ Object



86
87
88
# File 'lib/split/helper.rb', line 86

def override_alternative(experiment_name)
  params[experiment_name] if override_present?(experiment_name)
end

#override_present?(experiment_name) ⇒ Boolean

Returns:

  • (Boolean)


82
83
84
# File 'lib/split/helper.rb', line 82

def override_present?(experiment_name)
  defined?(params) && params[experiment_name]
end

#reset!(experiment) ⇒ Object



43
44
45
# File 'lib/split/helper.rb', line 43

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

#split_generically_disabled?Boolean

Returns:

  • (Boolean)


90
91
92
# File 'lib/split/helper.rb', line 90

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