Module: Split::Helper

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

def ab_test(metric_descriptor, control=nil, *alternatives)
  if RUBY_VERSION.match(/1\.8/) && alternatives.length.zero? && ! control.nil?
    puts 'WARNING: You should always pass the control alternative through as the second argument with any other alternatives as the third because the order of the hash is not preserved in ruby 1.8'
  end

  # Check if array is passed to ab_test: 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 => 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 && override_present?(experiment_name)
      ret = override_alternative(experiment_name)
    end
  ensure
    unless ret
      ret = control_variable(control)
    end
  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


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

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

#begin_experiment(experiment, alternative_name = nil) ⇒ Object


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

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


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

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)

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

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

#exclude_visitor?Boolean

Returns:

  • (Boolean)

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

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

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


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

def finish_experiment(experiment, options = {:reset => true})
  return true unless experiment.winner.nil?
  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])
    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)

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

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 request.ip == ip || (ip.class == Regexp && request.ip =~ ip)
  end
  false
end

#is_robot?Boolean

Returns:

  • (Boolean)

135
136
137
# File 'lib/split/helper.rb', line 135

def is_robot?
  request.user_agent =~ Split.configuration.robot_regex
end

#not_allowed_to_test?(experiment_key) ⇒ Boolean

Returns:

  • (Boolean)

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

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

#old_versions(experiment) ⇒ Object


126
127
128
129
130
131
132
133
# File 'lib/split/helper.rb', line 126

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


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

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