Class: Modesty::Experiment

Inherits:
Object
  • Object
show all
Defined in:
lib/modesty/experiment.rb,
lib/modesty/experiment/base.rb,
lib/modesty/experiment/data.rb,
lib/modesty/experiment/stats.rb,
lib/modesty/experiment/builder.rb,
lib/modesty/experiment/console.rb,
lib/modesty/experiment/interface.rb,
lib/modesty/experiment/significance.rb

Defined Under Namespace

Classes: ArgumentProxy, Builder, ConversionStat, DistributionStat, Error, Interface, Significance, Stat

Constant Summary collapse

ATTRIBUTES =
[
  :description,
]

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(slug) ⇒ Experiment

Returns a new instance of Experiment.



4
5
6
# File 'lib/modesty/experiment/base.rb', line 4

def initialize(slug)
  @slug = slug
end

Instance Attribute Details

#metrics(alt = nil) ⇒ Object (readonly)

Returns the value of attribute metrics.

Raises:



23
24
25
# File 'lib/modesty/experiment/base.rb', line 23

def metrics
  @metrics
end

#slugObject (readonly)

Returns the value of attribute slug.



22
23
24
# File 'lib/modesty/experiment/base.rb', line 22

def slug
  @slug
end

Instance Method Details

#aggregates(metric, *args) ⇒ Object



16
17
18
19
20
21
22
23
24
# File 'lib/modesty/experiment/stats.rb', line 16

def aggregates(metric, *args)
  metric = metric.slug if metric.is_a? Metric
  context = self.identity_for(metric)
  self.alternatives.hashmap do |a|
    agg = self.metrics(a)[metric].aggregate_by(context, *args)
    agg = agg.sum if agg.is_a?(Array)
    self.users(a).hashmap { 0 }.merge!(agg)
  end
end

#alternativesObject



29
30
31
# File 'lib/modesty/experiment/base.rb', line 29

def alternatives
  @alternatives ||= [:control, :experiment]
end

#chooses(alt, options = {}) ⇒ Object



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/modesty/experiment/data.rb', line 7

def chooses(alt, options={})
  raise Experiment::Error, <<-msg.squish unless self.alternatives.include? alt
    Unknown alternative #{alt.inspect}
  msg

  id = options.include?(:for) ? options[:for] : Modesty.identity

  raise IdentityError, <<-msg.squish unless id
    Experiment#chooses doesn't work for guests.
    Either identify globally or pass in :for => id
  msg

  self.data.register!(alt, id)
rescue Datastore::ConnectionError => e
  Modesty.handle_error(e)
  alt
end

#dataObject



3
4
5
# File 'lib/modesty/experiment/data.rb', line 3

def data
  @data ||= (Modesty.data.class)::ExperimentData.new(self)
end

#dist_analysis(metric, *args) ⇒ Object



32
33
34
35
36
# File 'lib/modesty/experiment/stats.rb', line 32

def dist_analysis(metric, *args)
  Significance.dist_significance(
    distributions(metric, *args)
  )
end

#distributions(metric, *args) ⇒ Object



26
27
28
29
30
# File 'lib/modesty/experiment/stats.rb', line 26

def distributions(metric, *args)
  aggregates(metric, *args).map_values! do |agg|
    agg.values.histogram
  end
end

#group(id = Modesty.identity) ⇒ Object



25
26
27
28
# File 'lib/modesty/experiment/data.rb', line 25

def group(id=Modesty.identity)
  return :control unless id
  fetch_or_generate_group(id)
end

#group?(alt) ⇒ Boolean

usage: ‘e.group?(:experiment)`

Returns:

  • (Boolean)


31
32
33
# File 'lib/modesty/experiment/data.rb', line 31

def group?(alt)
  self.group == alt
end

#identity_for(sym) ⇒ Object



16
17
18
19
# File 'lib/modesty/experiment/base.rb', line 16

def identity_for(sym)
  sym = sym.slug if sym.is_a? Metric
  self.metric_contexts[sym]
end

#inspectObject



8
9
10
# File 'lib/modesty/experiment/base.rb', line 8

def inspect
  "#<Modesty::Experiment[ #{self.slug.inspect} ]>"
end

#metric_contextsObject



25
26
27
# File 'lib/modesty/experiment/base.rb', line 25

def metric_contexts
  @metric_contexts ||= Hash.new(:user)
end

#num_users(alt = nil) ⇒ Object



35
36
37
38
39
40
41
# File 'lib/modesty/experiment/data.rb', line 35

def num_users(alt=nil)
  if self.data.respond_to? :num_users
    self.data.num_users(alt)
  else
    self.users(alt).count
  end
end

#reports(*args) ⇒ Object



12
13
14
# File 'lib/modesty/experiment/stats.rb', line 12

def reports(*args)
  self.stats.values.map { |s| s.report(*args) }
end

#statsObject



4
5
6
7
8
9
10
# File 'lib/modesty/experiment/stats.rb', line 4

def stats
  @stats ||= Hash.new do |hash, key|
    raise Error, <<-msg.squish
      Unrecognized stat #{key.inspect}
    msg
  end
end

#users(alt = nil) ⇒ Object



43
44
45
# File 'lib/modesty/experiment/data.rb', line 43

def users(alt=nil)
  self.data.users(alt)
end