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



36
37
38
# File 'app/models/experimental/experiment.rb', line 36

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

.activeObject



105
106
107
# File 'app/models/experimental/experiment.rb', line 105

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

.availableObject



101
102
103
# File 'app/models/experimental/experiment.rb', line 101

def self.available
  where(removed_at: nil)
end

.ended_or_removedObject



26
27
28
29
30
# File 'app/models/experimental/experiment.rb', line 26

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



16
17
18
# File 'app/models/experimental/experiment.rb', line 16

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

.in_progressObject



20
21
22
23
24
# File 'app/models/experimental/experiment.rb', line 20

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

.last_updated_atObject



32
33
34
# File 'app/models/experimental/experiment.rb', line 32

def self.last_updated_at
  maximum(:updated_at)
end

Instance Method Details

#active?Boolean

Returns:

  • (Boolean)


97
98
99
# File 'app/models/experimental/experiment.rb', line 97

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

#bucket(subject) ⇒ Object



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

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



113
114
115
116
# File 'app/models/experimental/experiment.rb', line 113

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



60
61
62
63
64
# File 'app/models/experimental/experiment.rb', line 60

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

#ended?Boolean

Returns:

  • (Boolean)


93
94
95
# File 'app/models/experimental/experiment.rb', line 93

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

#in?(subject) ⇒ Boolean

Returns:

  • (Boolean)


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

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



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

def remove
  result = false

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

  result
end

#removed?Boolean

Returns:

  • (Boolean)


89
90
91
# File 'app/models/experimental/experiment.rb', line 89

def removed?
  !removed_at.nil?
end

#restartObject



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

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



109
110
111
# File 'app/models/experimental/experiment.rb', line 109

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