class Experimental::Experiment

Public Class Methods

[](experiment_name) click to toggle source
# File lib/experimental/experiment.rb, line 41
def self.[](experiment_name)
  Experimental.source[experiment_name.to_s]
end
active() click to toggle source
# File lib/experimental/experiment.rb, line 120
def self.active
  now = Time.now
  available.where('start_date < ? AND end_date IS NULL OR ? <= end_date', now, now)
end
available() click to toggle source
# File lib/experimental/experiment.rb, line 116
def self.available
  where(removed_at: nil)
end
ended_or_removed() click to toggle source
# File lib/experimental/experiment.rb, line 31
def self.ended_or_removed
  where('removed_at is not null or end_date is not null').
    order(:removed_at).
    order('end_date desc')
end
in_code() click to toggle source
# File lib/experimental/experiment.rb, line 17
def self.in_code
  where(:removed_at => nil)
end
in_progress() click to toggle source
# File lib/experimental/experiment.rb, line 25
def self.in_progress
  where('start_date is not null and end_date is null and removed_at is null').
    order('start_date desc').
    order(:name)
end
last_updated_at() click to toggle source
# File lib/experimental/experiment.rb, line 37
def self.last_updated_at
  maximum(:updated_at)
end
unstarted() click to toggle source
# File lib/experimental/experiment.rb, line 21
def self.unstarted
  where(start_date: nil)
end

Public Instance Methods

active?() click to toggle source
# File lib/experimental/experiment.rb, line 112
def active?
  !removed? && started? && !ended?
end
bucket(subject) click to toggle source
# File lib/experimental/experiment.rb, line 45
def bucket(subject)
  if ended? || removed?
    winning_bucket
  elsif Experimental.overrides.include?(subject, name)
    Experimental.overrides[subject, name]
  elsif started?
    bucket_number(subject)
  end
end
bucket_number(subject) click to toggle source
# File lib/experimental/experiment.rb, line 129
def bucket_number(subject)
  top_8 = Digest::SHA1.hexdigest("#{name}#{subject.experiment_seed_value}")[0..7]
  top_8.to_i(16) % num_buckets
end
end(winning_num) click to toggle source
# File lib/experimental/experiment.rb, line 65
def end(winning_num)
  self.winning_bucket = winning_num
  self.end_date = Time.now
  save
end
ended?() click to toggle source
# File lib/experimental/experiment.rb, line 108
def ended?
  !end_date.nil? && Time.now > end_date
end
in?(subject) click to toggle source
# File lib/experimental/experiment.rb, line 55
def in?(subject)
  if removed?
    false
  elsif Experimental.overrides.include?(subject, name)
    !!Experimental.overrides[subject, name]
  else
    population_filter.in?(subject, self)
  end
end
remove() click to toggle source
# File lib/experimental/experiment.rb, line 90
def remove
  result = false

  unless removed?
    result = update_attribute(:removed_at, Time.now)
  end

  result
end
removed?() click to toggle source
# File lib/experimental/experiment.rb, line 100
def removed?
  !removed_at.nil?
end
restart() click to toggle source
# File lib/experimental/experiment.rb, line 79
def restart
  return unless ended?

  self.winning_bucket = nil
  self.start_date = Time.now
  self.end_date = nil
  self.removed_at = nil

  save
end
started?() click to toggle source
# File lib/experimental/experiment.rb, line 104
def started?
  start_date.present? && start_date <= Time.now
end
to_sql_formula(subject_table = "users") click to toggle source
# File lib/experimental/experiment.rb, line 125
def to_sql_formula(subject_table = "users")
  "CONV(SUBSTR(SHA1(CONCAT(\"#{name}\",#{subject_table}.id)),1,8),16,10) % #{num_buckets}"
end
unstart() click to toggle source
# File lib/experimental/experiment.rb, line 71
def unstart
  self.start_date = nil
  self.end_date = nil
  self.removed_at = nil
  self.winning_bucket = nil
  save
end

Private Instance Methods

population_filter() click to toggle source
# File lib/experimental/experiment.rb, line 151
def population_filter
  @population_filter ||= self.class.find_population(population)
end
validate_date(attribute) click to toggle source
# File lib/experimental/experiment.rb, line 141
def validate_date(attribute)
    value = read_attribute_before_type_cast(attribute)
    return if value.blank?
    begin
      return if value.to_time
    rescue ArgumentError
    end
    errors.add(attribute, "is not a valid date")
end
validate_dates() click to toggle source
# File lib/experimental/experiment.rb, line 136
def validate_dates
  validate_date 'start_date'
  validate_date 'end_date'
end