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
51
52
53
# 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
  # 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



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

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

#begin_experiment(experiment, alternative_name = nil) ⇒ Object



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

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



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

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)


123
124
125
# File 'lib/split/helper.rb', line 123

def doing_other_tests?(experiment_key)
  keys_without_experiment(ab_user.keys, experiment_key).length > 0
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)
end

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



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

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



78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/split/helper.rb', line 78

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)


146
147
148
149
150
151
152
153
# File 'lib/split/helper.rb', line 146

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)


142
143
144
# File 'lib/split/helper.rb', line 142

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

#not_allowed_to_test?(experiment_key) ⇒ Boolean

Returns:

  • (Boolean)


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

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

#old_versions(experiment) ⇒ Object



133
134
135
136
137
138
139
140
# File 'lib/split/helper.rb', line 133

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



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

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

#override_present?(experiment_name) ⇒ Boolean

Returns:

  • (Boolean)


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

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

#reset!(experiment) ⇒ Object



55
56
57
# File 'lib/split/helper.rb', line 55

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

#split_generically_disabled?Boolean

Returns:

  • (Boolean)


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

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