Class: Experimental::Experiment

Inherits:
ActiveRecord::Base
  • Object
show all
Extended by:
Population::Filter
Defined in:
app/models/experimental/experiment.rb

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Population::Filter

extended, find_population, register_population_filter, reset_population_filters

Class Method Details

.[](experiment_name) ⇒ Object



34
35
36
# File 'app/models/experimental/experiment.rb', line 34

def self.[](experiment_name)
  Experimental.source[experiment_name.to_s]
end

.activeObject



103
104
105
# File 'app/models/experimental/experiment.rb', line 103

def self.active
  available.where(['end_date IS NULL OR ? <= end_date', Time.now])
end

.availableObject



99
100
101
# File 'app/models/experimental/experiment.rb', line 99

def self.available
  where(removed_at: nil)
end

.ended_or_removedObject



24
25
26
27
28
# File 'app/models/experimental/experiment.rb', line 24

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_codeObject



14
15
16
# File 'app/models/experimental/experiment.rb', line 14

def self.in_code
  where(:removed_at => nil)
end

.in_progressObject



18
19
20
21
22
# File 'app/models/experimental/experiment.rb', line 18

def self.in_progress
  where('removed_at is null and end_date is null').
    order('start_date desc').
    order(:name)
end

.last_updated_atObject



30
31
32
# File 'app/models/experimental/experiment.rb', line 30

def self.last_updated_at
  maximum(:updated_at)
end

Instance Method Details

#active?Boolean

Returns:

  • (Boolean)


95
96
97
# File 'app/models/experimental/experiment.rb', line 95

def active?
  !removed? && !ended?
end

#bucket(subject) ⇒ Object



38
39
40
41
42
43
44
45
46
# File 'app/models/experimental/experiment.rb', line 38

def bucket(subject)
  if ended? || removed?
    winning_bucket
  elsif Experimental.overrides.include?(subject, name)
    Experimental.overrides[subject, name]
  else
    bucket_number(subject)
  end
end

#bucket_number(subject) ⇒ Object



111
112
113
114
# File 'app/models/experimental/experiment.rb', line 111

def bucket_number(subject)
  top_8 = Digest::SHA1.hexdigest("#{name}#{subject.id}")[0..7]
  top_8.to_i(16) % num_buckets
end

#end(winning_num) ⇒ Object



58
59
60
61
62
# File 'app/models/experimental/experiment.rb', line 58

def end(winning_num)
  self.winning_bucket = winning_num
  self.end_date = Time.now
  save
end

#ended?Boolean

Returns:

  • (Boolean)


91
92
93
# File 'app/models/experimental/experiment.rb', line 91

def ended?
  !end_date.nil? && Time.now > end_date
end

#in?(subject) ⇒ Boolean

Returns:

  • (Boolean)


48
49
50
51
52
53
54
55
56
# File 'app/models/experimental/experiment.rb', line 48

def in?(subject)
  if removed?
    false
  elsif Experimental.overrides.include?(subject, name)
    !!Experimental.overrides[subject, name]
  else
    population_filter.in?(subject, self)
  end
end

#removeObject



75
76
77
78
79
80
81
82
83
84
85
# File 'app/models/experimental/experiment.rb', line 75

def remove
  result = false

  unless removed?
    result = update_attributes(
      { removed_at: Time.now }, without_protection: true
    )
  end

  result
end

#removed?Boolean

Returns:

  • (Boolean)


87
88
89
# File 'app/models/experimental/experiment.rb', line 87

def removed?
  !removed_at.nil?
end

#restartObject



64
65
66
67
68
69
70
71
72
73
# File 'app/models/experimental/experiment.rb', line 64

def restart
  return unless ended?

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

  save
end

#to_sql_formula(subject_table = "users") ⇒ Object



107
108
109
# File 'app/models/experimental/experiment.rb', line 107

def to_sql_formula(subject_table = "users")
  "CONV(SUBSTR(SHA1(CONCAT(\"#{name}\",#{subject_table}.id)),1,8),16,10) % #{num_buckets}"
end