Skip to content
This repository has been archived by the owner on Jan 1, 2024. It is now read-only.

Commit

Permalink
Remove hard Redis gem dependency from gemspec.
Browse files Browse the repository at this point in the history
* Closes #138
* Adds documentation to README.
* Moves redis dependency checking to adapter.
  • Loading branch information
phillbaker committed Nov 28, 2013
1 parent 528a1fa commit 9fffd83
Show file tree
Hide file tree
Showing 17 changed files with 69 additions and 32 deletions.
2 changes: 2 additions & 0 deletions Gemfile
Expand Up @@ -9,6 +9,8 @@ gem "rails", "~>2.3.8"
gem "passenger", "~>2.0"

# Persistence
gem "redis", ">= 2.1"
gem "redis-namespace", ">= 1.1.0"
gem "bson_ext"
gem "mongo"
gem "mysql"
Expand Down
4 changes: 2 additions & 2 deletions Gemfile.lock
Expand Up @@ -2,8 +2,6 @@ PATH
remote: .
specs:
vanity (1.8.3)
redis (>= 2.1)
redis-namespace (>= 1.1.0)

GEM
remote: https://rubygems.org/
Expand Down Expand Up @@ -110,6 +108,8 @@ DEPENDENCIES
rack
rails (~> 2.3.8)
rake
redis (>= 2.1)
redis-namespace (>= 1.1.0)
rubystats
shoulda
timecop
Expand Down
22 changes: 19 additions & 3 deletions README.rdoc
@@ -1,7 +1,7 @@
= Vanity
{<img src="https://travis-ci.org/assaf/vanity.png?branch=master" alt="Build Status" />}[https://travis-ci.org/assaf/vanity]

Vanity is an Experiment Driven Development framework for Rails.
Vanity is an A/B testing framework for Rails that is datastore agnostic.

* All about Vanity: http://vanity.labnotes.org
* On Github: http://github.com/assaf/vanity
Expand Down Expand Up @@ -33,14 +33,30 @@ Add to your Gemfile:

==== Step 1.2

Choose a method to store experiment results: for Redis or an external tracking mechanism, migrations aren't needed. Mongo is also available. To use a relational database, via ActiveRecord, run the generator and migrations to create the database schema:
Choose a method to store experiment results.

For Redis:

gem "redis", ">= 2.1"
gem "redis-namespace", ">= 1.1.0"

For Mongo:

gem "bson_ext"
gem "mongo"

Vanity supports multiple SQL stores (like MySQL, MariaDB, Postgres, Sqlite, etc.) using ActiveRecord, which is built into Rails. If you're using DataMapper, Sequel or another persistence framework:

gem "active_record"

Fun the generator and migrations to create the database schema:

$ rails generate vanity
$ rake db:migrate

==== Step 1.3

add to your application controller:
Turn Vanity on, and pass a reference to a method that identifies a user. For example:

class ApplicationController < ActionController::Base
use_vanity :current_user
Expand Down
2 changes: 2 additions & 0 deletions gemfiles/rails3.gemfile
Expand Up @@ -3,6 +3,8 @@
source "https://rubygems.org"

gem "rack"
gem "redis", ">= 2.1"
gem "redis-namespace", ">= 1.1.0"
gem "bson_ext"
gem "mongo"
gem "mysql"
Expand Down
4 changes: 2 additions & 2 deletions gemfiles/rails3.gemfile.lock
Expand Up @@ -8,8 +8,6 @@ PATH
remote: ..
specs:
vanity (1.8.3)
redis (>= 2.1)
redis-namespace (>= 1.1.0)

GEM
remote: https://rubygems.org/
Expand Down Expand Up @@ -165,6 +163,8 @@ DEPENDENCIES
rack
rails (= 3.0.11)
rake
redis (>= 2.1)
redis-namespace (>= 1.1.0)
rubystats
shoulda
timecop
Expand Down
2 changes: 2 additions & 0 deletions gemfiles/rails31.gemfile
Expand Up @@ -3,6 +3,8 @@
source "https://rubygems.org"

gem "rack"
gem "redis", ">= 2.1"
gem "redis-namespace", ">= 1.1.0"
gem "bson_ext"
gem "mongo"
gem "mysql"
Expand Down
4 changes: 2 additions & 2 deletions gemfiles/rails31.gemfile.lock
Expand Up @@ -8,8 +8,6 @@ PATH
remote: ..
specs:
vanity (1.8.3)
redis (>= 2.1)
redis-namespace (>= 1.1.0)

GEM
remote: https://rubygems.org/
Expand Down Expand Up @@ -174,6 +172,8 @@ DEPENDENCIES
rack
rails (= 3.1.3)
rake
redis (>= 2.1)
redis-namespace (>= 1.1.0)
rubystats
shoulda
timecop
Expand Down
2 changes: 2 additions & 0 deletions gemfiles/rails32.gemfile
Expand Up @@ -3,6 +3,8 @@
source "https://rubygems.org"

gem "rack"
gem "redis", ">= 2.1"
gem "redis-namespace", ">= 1.1.0"
gem "bson_ext"
gem "mongo"
gem "mysql"
Expand Down
4 changes: 2 additions & 2 deletions gemfiles/rails32.gemfile.lock
Expand Up @@ -8,8 +8,6 @@ PATH
remote: ..
specs:
vanity (1.8.3)
redis (>= 2.1)
redis-namespace (>= 1.1.0)

GEM
remote: https://rubygems.org/
Expand Down Expand Up @@ -174,6 +172,8 @@ DEPENDENCIES
rack
rails (= 3.2.1)
rake
redis (>= 2.1)
redis-namespace (>= 1.1.0)
rubystats
shoulda
timecop
Expand Down
2 changes: 2 additions & 0 deletions gemfiles/rails4.gemfile
Expand Up @@ -3,6 +3,8 @@
source "https://rubygems.org"

gem "rack"
gem "redis", ">= 2.1"
gem "redis-namespace", ">= 1.1.0"
gem "bson_ext"
gem "mongo"
gem "mysql"
Expand Down
4 changes: 2 additions & 2 deletions gemfiles/rails4.gemfile.lock
Expand Up @@ -8,8 +8,6 @@ PATH
remote: ..
specs:
vanity (1.8.3)
redis (>= 2.1)
redis-namespace (>= 1.1.0)

GEM
remote: https://rubygems.org/
Expand Down Expand Up @@ -172,6 +170,8 @@ DEPENDENCIES
rack
rails (= 4.0.0)
rake
redis (>= 2.1)
redis-namespace (>= 1.1.0)
rubystats
shoulda
timecop
Expand Down
2 changes: 0 additions & 2 deletions lib/vanity.rb
Expand Up @@ -26,8 +26,6 @@ module Vanity
require "vanity/experiment/ab_test"
# Database adapters
require "vanity/adapters/abstract_adapter"
require "vanity/adapters/redis_adapter"
require "vanity/adapters/mongodb_adapter"
require "vanity/adapters/mock_adapter"
# Playground.
require "vanity/playground"
Expand Down
6 changes: 4 additions & 2 deletions lib/vanity/adapters/active_record_adapter.rb
Expand Up @@ -86,6 +86,8 @@ def self.retrieve(experiment, identity, create = true, update_with = nil)
end

def initialize(options)


@options = options.inject({}) { |h,kv| h[kv.first.to_s] = kv.last ; h }
if @options["active_record_adapter"] && (@options["active_record_adapter"] != "default")
@options["adapter"] = @options["active_record_adapter"]
Expand Down Expand Up @@ -222,8 +224,8 @@ def ab_add_participant(experiment, alternative, identity)

# Determines if a participant already has seen this alternative in this experiment.
def ab_seen(experiment, identity, alternative)
participant = VanityParticipant.retrieve(experiment, identity, false)
participant && participant.seen == alternative.id
participant = VanityParticipant.retrieve(experiment, identity, false)
participant && participant.seen == alternative.id
end

# Returns the participant's seen alternative in this experiment, if it exists
Expand Down
12 changes: 6 additions & 6 deletions lib/vanity/adapters/mongodb_adapter.rb
Expand Up @@ -73,10 +73,10 @@ def flushdb
@experiments.drop
@participants.drop
end


# -- Metrics --

def get_metric_last_update_at(metric)
record = @metrics.find_one(:_id=>metric)
record && record["last_update_at"]
Expand All @@ -99,10 +99,10 @@ def metric_values(metric, from, to)
def destroy_metric(metric)
@metrics.remove :_id=>metric
end


# -- Experiments --

def set_experiment_created_at(experiment, time)
@experiments.insert :_id=>experiment, :created_at=>time
end
Expand Down Expand Up @@ -152,8 +152,8 @@ def ab_add_participant(experiment, alternative, identity)

# Determines if a participant already has seen this alternative in this experiment.
def ab_seen(experiment, identity, alternative)
participant = @participants.find_one({ :experiment=>experiment, :identity=>identity }, { :fields=>[:seen] })
participant && participant["seen"].first == alternative.id
participant = @participants.find_one({ :experiment=>experiment, :identity=>identity }, { :fields=>[:seen] })
participant && participant["seen"].first == alternative.id
end

# Returns the participant's seen alternative in this experiment, if it exists
Expand Down
26 changes: 19 additions & 7 deletions lib/vanity/adapters/redis_adapter.rb
Expand Up @@ -5,9 +5,21 @@ class << self
#
# @since 1.4.0
def redis_connection(spec)
require "redis"
fail "redis >= 2.1 is required" unless valid_redis_version?
require "redis/namespace"
fail "redis-namespace >= 1.1.0 is required" unless valid_redis_namespace_version?

RedisAdapter.new(spec)
end

def valid_redis_version?
Gem.loaded_specs['redis'].version >= Gem::Version.create('2.1')
end

def valid_redis_namespace_version?
Gem.loaded_specs['redis'].version >= Gem::Version.create('1.1.0')
end
end

# Redis adapter.
Expand Down Expand Up @@ -60,7 +72,7 @@ def flushdb
end

# -- Metrics --

def get_metric_last_update_at(metric)
last_update_at = @metrics["#{metric}:last_update_at"]
last_update_at && Time.at(last_update_at.to_i)
Expand All @@ -84,7 +96,7 @@ def destroy_metric(metric)


# -- Experiments --

def set_experiment_created_at(experiment, time)
@experiments.setnx "#{experiment}:created_at", time.to_i
end
Expand Down Expand Up @@ -131,11 +143,11 @@ def ab_add_participant(experiment, alternative, identity)
end

def ab_seen(experiment, identity, alternative)
if @experiments.sismember "#{experiment}:alts:#{alternative.id}:participants", identity
return alternative
else
return nil
end
if @experiments.sismember "#{experiment}:alts:#{alternative.id}:participants", identity
return alternative
else
return nil
end
end

# Returns the participant's seen alternative in this experiment, if it exists
Expand Down
1 change: 1 addition & 0 deletions test/adapters/redis_adapter_test.rb
Expand Up @@ -3,6 +3,7 @@
class RedisAdapterTest < Test::Unit::TestCase
def test_warn_on_disconnect_error
if defined?(Redis)
require "vanity/adapters/redis_adapter"
assert_nothing_raised do
Redis.any_instance.stubs(:connect!)
mocked_redis = stub("Redis")
Expand Down
2 changes: 0 additions & 2 deletions vanity.gemspec
Expand Up @@ -22,6 +22,4 @@ Gem::Specification.new do |spec|
"--webcvs", "http://github.com/assaf/#{spec.name}"

spec.required_ruby_version = ">= 1.8.7"
spec.add_dependency "redis", ">= 2.1"
spec.add_dependency "redis-namespace", ">= 1.1.0"
end

0 comments on commit 9fffd83

Please sign in to comment.