Skip to content

Commit

Permalink
Revert "rm experiment data methods for stability"
Browse files Browse the repository at this point in the history
This reverts commit 211731b.
  • Loading branch information
Kristján Pétursson committed Nov 9, 2010
1 parent 63783f1 commit a2a9899
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 3 deletions.
48 changes: 48 additions & 0 deletions lib/modesty/datastore/redis.rb
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,54 @@ def track!(count, with_args)
end
end
end

end

class ExperimentData < Datastore::ExperimentData
def data
Modesty.data
end

def key(*args)
RedisData.keyify(:experiments, @experiment.slug, *args)
end

def register!(alt, identity)
old_alt = self.get_cached_alternative(identity)
if old_alt
data.srem(self.key(old_alt), identity)
end
data.sadd(self.key(alt), identity)
return alt
end

def get_cached_alternative(identity)
@experiment.alternatives.each do |alt|
if data.sismember(self.key(alt), identity)
return alt
end
end
return nil
end

def users(alt=nil)
if alt.nil? #return the union
data.sunion(*@experiment.alternatives.map {|a| self.key(a) })
else
data.smembers(self.key(alt))
end.map(&:to_i)
end

def num_users(alt=nil)
if alt.nil?
@experiment.alternatives.map do |alt|
data.scard(self.key(alt)).to_i
end.sum
else
data.scard(self.key(alt)).to_i
end
end

end
end
end
66 changes: 63 additions & 3 deletions lib/modesty/experiment/data.rb
Original file line number Diff line number Diff line change
@@ -1,15 +1,75 @@
module Modesty
class Experiment
def data
@data ||= (Modesty.data.class)::ExperimentData.new(self)
end

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

def group(id=Modesty.identity)
return :control unless id
self.alternatives[
"#{@slug}#{id}".hash % self.alternatives.count
]
fetch_or_generate_group(id)
end

# usage: `e.group?(:experiment)`
def group?(alt)
self.group == alt
end

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

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

private
# used to fetch the cached alternative from redis
def fetch_group(identity)
self.data.get_cached_alternative(identity)
rescue Datastore::ConnectionError => e
Modesty.handle_error(e)
nil
end

# this is the method with the fallbacks - fetch it from redis or create it.
def fetch_or_generate_group(id=Modesty.identity)
alt = begin
fetch_group(id)
rescue Datastore::ConnectionError
nil
end || generate_group(id)
end

# generates an alternative and stores it in redis
def generate_group(identity)
alternative = self.alternatives[
"#{@slug}#{identity}".hash % self.alternatives.count
]
self.chooses(alternative, :for => identity)
return alternative
end

end
end

0 comments on commit a2a9899

Please sign in to comment.