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
42
43
44
45
46
47
48
49
50
# File 'lib/split/helper.rb', line 4

def ab_test(metric_descriptor, control=nil, *alternatives)

  # Check if array is passed to ab_test
  # e.g. ab_test('name', ['Alt 1', 'Alt 2', 'Alt 3'])
  if control.is_a? Array and alternatives.length.zero?
    control, alternatives = control.first, control[1..-1]
  end

  begin
    experiment_name_with_version, goals = normalize_experiment(metric_descriptor)
    experiment_name = experiment_name_with_version.to_s.split(':')[0]
    experiment = Split::Experiment.new(
      experiment_name,
      :alternatives => [control].compact + alternatives,
      :goals => goals)
    control ||= experiment.control && experiment.control.name

    ret = if Split.configuration.enabled
      experiment.save
      start_trial( Trial.new(:experiment => experiment) )
    else
      control_variable(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
      ret = override_alternative(experiment_name) if override_present?(experiment_name)
      ret = control_variable(control) if split_generically_disabled?
    end
  ensure
    ret ||= control_variable(control)
  end

  if block_given?
    if defined?(capture) # a block in a rails view
      block = Proc.new { yield(ret) }
      concat(capture(ret, &block))
      false
    else
      yield(ret)
    end
  else
    ret
  end
end

#ab_userObject



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

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

#begin_experiment(experiment, alternative_name = nil) ⇒ Object



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

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

#clean_old_versions(experiment) ⇒ Object



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

def clean_old_versions(experiment)
  old_versions(experiment).each do |old_key|
    ab_user.delete old_key
  end
end

#doing_other_tests?(experiment_key) ⇒ Boolean

Returns:

  • (Boolean)


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

def doing_other_tests?(experiment_key)
  keys_without_experiment(ab_user.keys, experiment_key).length > 0
end

#exclude_visitor?Boolean

Returns:

  • (Boolean)


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

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

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



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/split/helper.rb', line 56

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(:experiment => experiment, :alternative => alternative_name, :goals => options[:goals])
    call_trial_complete_hook(trial) if trial.complete!

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

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



75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/split/helper.rb', line 75

def finished(metric_descriptor, options = {:reset => true})
  return if exclude_visitor? || Split.configuration.disabled?
  metric_descriptor, goals = normalize_experiment(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)


143
144
145
146
147
148
149
150
# File 'lib/split/helper.rb', line 143

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)


139
140
141
# File 'lib/split/helper.rb', line 139

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

#not_allowed_to_test?(experiment_key) ⇒ Boolean

Returns:

  • (Boolean)


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

def not_allowed_to_test?(experiment_key)
  !Split.configuration.allow_multiple_experiments && doing_other_tests?(experiment_key)
end

#old_versions(experiment) ⇒ Object



130
131
132
133
134
135
136
137
# File 'lib/split/helper.rb', line 130

def old_versions(experiment)
  if experiment.version > 0
    keys = ab_user.keys.select { |k| k.match(Regexp.new(experiment.name)) }
    keys_without_experiment(keys, experiment.key)
  else
    []
  end
end

#override_alternative(experiment_name) ⇒ Object



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

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

#override_present?(experiment_name) ⇒ Boolean

Returns:

  • (Boolean)


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

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

#reset!(experiment) ⇒ Object



52
53
54
# File 'lib/split/helper.rb', line 52

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

#split_generically_disabled?Boolean

Returns:

  • (Boolean)


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

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