fabes 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.0.2
data/fabes.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "fabes"
8
- s.version = "0.0.1"
8
+ s.version = "0.0.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Alejandro Andres"]
12
- s.date = "2012-07-23"
12
+ s.date = "2012-07-25"
13
13
  s.description = "Fabes is an A/B testing system for your ruby projects"
14
14
  s.email = "fuzzy.alej@gmail.com"
15
15
  s.extra_rdoc_files = [
@@ -39,6 +39,7 @@ Gem::Specification.new do |s|
39
39
  "lib/fabes/connection_handling.rb",
40
40
  "lib/fabes/experiment.rb",
41
41
  "lib/fabes/helper.rb",
42
+ "lib/fabes/railtie.rb",
42
43
  "lib/fabes/utils.rb",
43
44
  "test/helper.rb",
44
45
  "test/test_abstract_adapter.rb",
data/lib/fabes.rb CHANGED
@@ -17,15 +17,10 @@ module Fabes
17
17
  end
18
18
 
19
19
  def db
20
- @db ||= ConnectionHandling.establish_connection Fabes.configuration.db, Fabes.configuration.adapter
20
+ @db ||= ConnectionHandling.establish_connection Fabes.configuration.database
21
21
  end
22
22
  end
23
23
 
24
24
  Fabes.configure
25
25
 
26
- if defined? Rails
27
- ActionController::Base.send :include, Fabes::Helper
28
- ActionController::Base.helper Fabes::Helper
29
- #TODO: Autoadd route to admin panel
30
- #TODO: Railtie???
31
- end
26
+ require 'fabes/railtie' if defined? Rails
@@ -1,7 +1,8 @@
1
1
  body {
2
- font: normal 12px auto Verdana, Arial, Helvetica, sans-serif;
3
- color: #FDF3E7;
4
- background: #3B3738;
2
+ font-family: 'trebuchet MS', 'Lucida sans', Arial, sans-serif;
3
+ font-size: 14px;
4
+ color: #3b3b3b;
5
+ background-image: url('http://subtlepatterns.com/patterns/fabric_plaid.png');
5
6
  }
6
7
 
7
8
  a {
@@ -18,38 +19,103 @@ h2.span {
18
19
  font-size: 16px;
19
20
  }
20
21
 
22
+ #logo {
23
+ margin-bottom: 25px;
24
+ }
25
+
26
+ #logo h1 {
27
+ font-family: Arial, sans-serif;
28
+ font-size: 75px;
29
+ margin: 25px 0 0 0;
30
+ color: #504f4f;
31
+ text-shadow: 0px 2px 1px #bbbaba;
32
+ }
33
+
34
+ #logo span {
35
+ text-shadow: 0px 1px 1px #bbbaba;
36
+ }
37
+
21
38
  table {
22
39
  width: 700px;
23
40
  padding: 0px;
24
41
  margin: 0px;
42
+ border: solid 1px #999;
43
+ *border-collapse: collapse;
44
+ border-spacing: 0;
45
+ border-radius: 6px;
46
+ -moz-border-radius: 6px;
47
+ -wekit-border-radius: 6px;
48
+ box-shadow: 0 1px 1px #999;
49
+ -webkit-box-shadow: 0 1px 1px #999;
50
+ -moz-box-shadow: 0 1px 1px #999;
25
51
  }
26
52
 
27
53
  th {
28
- border-right: 1px solid #A64C2E;
29
- border-bottom: 1px solid #A64C2E;
30
- border-top: 1px solid #D53500;
31
- border-left: 1px solid #D53500;
32
54
  letter-spacing: 2px;
33
55
  text-transform: uppercase;
34
56
  text-align: center;
35
57
  font-size: 13px;
36
58
  padding: 10px;
37
- background: #C63D0F;
38
59
  color: #FFFFFF;
60
+ background-color: #C63D0F;
61
+ background-image: linear-gradient(top, #c63d0f, #6f1b00);
62
+ background-image: -webkit-linear-gradient(top, #c63d0f, #6f1b00);
63
+ background-image: -moz-linear-gradient(top, #c63d0f, #6f1b00);
39
64
  text-shadow: 1px 1px 1px black;
65
+ box-shadow: 0 1px 0 rgba(255, 200, 200, .8) inset;
66
+ -moz-box-shadow: 0 1px 0 rgba(255, 200, 200, .8) inset;
67
+ -webkit-box-shadow: 0 1px 0 rgba(255, 200, 200, .8) inset;
68
+ }
69
+
70
+ th:first-child {
71
+ background-color: #C63D0F;
72
+ background-image: linear-gradient(top, #c63d0f, #6f1b00)
73
+ background-image: -webkit-linear-gradient(top, #c63d0f, #6f1b00);
74
+ background-image: -moz-linear-gradient(top, #c63d0f, #6f1b00);
75
+ -moz-border-radius: 6px 0 0 0;
76
+ -webkit-border-radius: 6px 0 0 0;
77
+ border-radius: 6px 0 0 0;
78
+ }
79
+
80
+ th:last-child {
81
+ -moz-border-radius: 0 6px 0 0;
82
+ -webkit-border-radius: 0 6px 0 0;
83
+ border-radius: 0 6px 0 0;
40
84
  }
41
85
 
42
86
  td {
43
87
  border-right: 1px solid #C1DAD7;
44
88
  border-bottom: 1px solid #C1DAD7;
45
- background: #FDF3E7;
46
89
  padding: 6px;
47
90
  color: #3B3738;
48
- font-size: 13px;
91
+ }
92
+
93
+ td:first-child {
94
+ font-weight: bold;
95
+ }
96
+
97
+ tr {
98
+ background: white;
99
+ }
100
+
101
+ tr:last-child td:first-child {
102
+ border-radius: 0 0 0 6px;
103
+ -moz-border-radius: 0 0 0 6px;
104
+ -webkit-border-radius: 0 0 0 6px;
105
+ }
106
+
107
+ tr:last-child td:last-child {
108
+ border-radius: 0 0 6px 0;
109
+ -moz-border-radius: 0 0 6px 0;
110
+ -webkit-border-radius: 0 0 6px 0;
111
+ }
112
+
113
+ tr:hover {
114
+ background: #FBF8E9;
49
115
  }
50
116
 
51
117
  #container {
52
- margin: 50px auto;
118
+ margin: 0 auto;
53
119
  text-align: center;
54
120
  overflow: hidden;
55
121
  }
@@ -4,14 +4,16 @@
4
4
  .experiment
5
5
  %h2= "Experiment: #{name.capitalize}"
6
6
  %table{id: name.first, cellspacing: 0, summary: "Data for experiment '#{name}'"}
7
- %tr
8
- %th{scope: 'col'} Alternative
9
- %th{scope: 'col'} Participants
10
- %th{scope: 'col'} Hits
11
- %th{scope: 'col'} Weight
12
- - experiment.alternatives.each do |alternative|
7
+ %thead
13
8
  %tr
14
- %td{title: alternative.id}= alternative.payload
15
- %td= alternative.participants
16
- %td= alternative.hits
17
- %td= alternative.weight
9
+ %th{scope: 'col'} Alternative
10
+ %th{scope: 'col'} Participants
11
+ %th{scope: 'col'} Hits
12
+ %th{scope: 'col'} Weight
13
+ %tbody
14
+ - experiment.alternatives.each do |alternative|
15
+ %tr
16
+ %td{title: alternative.id}= alternative.payload
17
+ %td= alternative.participants
18
+ %td= alternative.hits
19
+ %td= alternative.weight
@@ -5,7 +5,8 @@
5
5
  %link{href: request.env['SCRIPT_NAME'] + '/application.css', media: 'all', rel: 'stylesheet', type: 'text/css'}
6
6
  %body
7
7
  #container
8
- #header
9
- .logo
8
+ #logo
9
+ %h1 Fabes
10
+ %span Fabulous A/B Experimentation System
10
11
  #content
11
12
  =yield
@@ -1,17 +1,20 @@
1
1
  module Fabes
2
2
  class Configuration
3
- attr_accessor :adapter, :db
3
+ attr_accessor :database, :factor
4
4
 
5
5
  def initialize
6
- @adapter = 'redis'
7
- @db = nil
6
+ @database = ENV['FABES_DB_URL'] || ENV['REDISTOGO_URL']
7
+ @factor = 0.1
8
8
  end
9
9
 
10
- def use(db_config)
11
- @adapter = db_config[:adapter].to_s
12
- @db = db_config[:db] || ENV['FABES_DB_URL'] || ENV['REDISTOGO_URL']
13
- rescue => e
14
- raise "Bad 'use' config: #{e.message}"
10
+ def use(options)
11
+ @database = options[:database] || options [:db]
12
+ rescue
13
+ @database = nil
14
+ end
15
+
16
+ def bandit_factor(percentage)
17
+ @factor = percentage
15
18
  end
16
19
  end
17
20
  end
@@ -1,17 +1,31 @@
1
1
  module Fabes
2
2
  module ConnectionHandling
3
+ require 'ostruct'
3
4
  extend self
4
5
 
5
- def establish_connection(db, adapter)
6
- #TODO: automagically parse db a la rails
7
- #REF: https://github.com/rails/rails/blob/master/activerecord/lib/active_record/connection_handling.rb
6
+ def establish_connection(db)
7
+ database = connection_url_to_hash(db)
8
+ adapter = database.delete :adapter
8
9
  adapter_method = "#{adapter}_connection"
9
- send adapter_method, db
10
- rescue => e
10
+ send adapter_method, database
11
+ rescue
11
12
  raise "Could not find #{adapter} adapter!"
12
13
  end
13
14
 
14
- def parse_connection_url(url)
15
+ #from https://github.com/rails/rails/blob/master/activerecord/lib/active_record/connection_adapters/connection_specification.rb#L65
16
+ def connection_url_to_hash(url)
17
+ url ||= ''
18
+ uri = URI.parse url
19
+ spec = {
20
+ host: uri.host,
21
+ port: uri.port,
22
+ adapter: uri.scheme,
23
+ username: uri.user,
24
+ password: uri.password,
25
+ database: uri.path.sub(%r{^/}, '')
26
+ }
27
+ spec.reject! {|_, value| !value}
28
+ {adapter: 'redis'}.merge spec
15
29
  end
16
30
  end
17
31
 
@@ -2,8 +2,8 @@ module Fabes
2
2
  module ConnectionHandling
3
3
  def self.redis_connection(db)
4
4
  require 'redis'
5
- db ||= ::Redis.new
6
- ConnectionAdapters::RedisAdapter.new(db)
5
+ redis = ::Redis.new db
6
+ ConnectionAdapters::RedisAdapter.new redis
7
7
  end
8
8
  end
9
9
 
@@ -52,7 +52,7 @@ module Fabes
52
52
  private
53
53
 
54
54
  def exploration?
55
- rand() < 0.2 # 20% of times
55
+ rand() < Fabes.configuration.factor.to_f
56
56
  end
57
57
 
58
58
  def random_alternative
@@ -0,0 +1,7 @@
1
+ module Fabes
2
+ class FabesRailtie < ::Rails::Railtie
3
+ ActionController::Base.send :include, Fabes::Helper
4
+ ActionController::Base.helper Fabes::Helper
5
+ #TODO: auto-inject route in rails?
6
+ end
7
+ end
@@ -4,17 +4,15 @@ class TestAbstractAdapter < Test::Unit::TestCase
4
4
  context 'establish_connection' do
5
5
  should 'raise if no suitable adapter' do
6
6
  assert_raise RuntimeError do
7
- adapter = 'caca'
8
- db = ''
9
- Fabes::ConnectionHandling.establish_connection(db, adapter)
7
+ db = 'http://uno:dos@tres.com:123/'
8
+ Fabes::ConnectionHandling.establish_connection(db)
10
9
  end
11
10
  end
12
11
 
13
12
  should 'work if suitable adapter (redis)' do
14
- adapter = 'redis'
15
- db = ''
13
+ db = 'redis://uno:dos@tres.com:123/'
16
14
  Fabes::ConnectionHandling.expects :redis_connection
17
- Fabes::ConnectionHandling.establish_connection(db, adapter)
15
+ Fabes::ConnectionHandling.establish_connection(db)
18
16
  end
19
17
  end
20
18
  end
@@ -2,9 +2,14 @@ require 'helper'
2
2
 
3
3
  class TestConfiguration < Test::Unit::TestCase
4
4
  context 'initialization' do
5
- should 'have an adapter' do
5
+ should 'have a database' do
6
6
  configuration = Fabes::Configuration.new
7
- assert configuration.respond_to? :adapter
7
+ assert configuration.respond_to? :database
8
+ end
9
+
10
+ should 'have a factor' do
11
+ configuration = Fabes::Configuration.new
12
+ assert configuration.respond_to? :factor
8
13
  end
9
14
  end
10
15
 
@@ -14,20 +19,30 @@ class TestConfiguration < Test::Unit::TestCase
14
19
  assert configuration.respond_to? :use
15
20
  end
16
21
 
17
- should 'set the adapter' do
22
+ should 'have a factor command' do
23
+ configuration = Fabes::Configuration.new
24
+ assert configuration.respond_to? :factor
25
+ end
26
+
27
+ should 'set the database' do
28
+ configuration = Fabes.configure do |c|
29
+ c.use database: 'redis://user:pwd@host.com:123/'
30
+ end
31
+ assert_not_nil configuration.instance_variable_get :@database
32
+ end
33
+
34
+ should 'nilify the db with bad configuration' do
18
35
  configuration = Fabes.configure do |c|
19
- c.use db: 'abc', adapter: :redis
36
+ c.use fail: 'redis://user:pwd@host.com:123/'
20
37
  end
21
- assert_not_nil configuration.instance_variable_get :@adapter
22
- assert_equal configuration.instance_variable_get(:@adapter), 'redis'
38
+ assert_nil configuration.instance_variable_get :@database
23
39
  end
24
40
 
25
- should 'set the db' do
41
+ should 'set the factor' do
26
42
  configuration = Fabes.configure do |c|
27
- c.use db: 'abc', adapter: :redis
43
+ c.bandit_factor 0.25
28
44
  end
29
- assert_not_nil configuration.instance_variable_get(:@db)
30
- assert_equal configuration.instance_variable_get(:@db), 'abc'
45
+ assert_equal configuration.factor, 0.25
31
46
  end
32
47
  end
33
48
  end
@@ -15,6 +15,7 @@ class TestRedisAdapter < Test::Unit::TestCase
15
15
  setup do
16
16
  @db = Redis.new
17
17
  @adapter = Fabes::ConnectionAdapters::RedisAdapter.new(@db)
18
+ Fabes.stubs(:db).returns(@adapter)
18
19
  @experiment = Fabes::Experiment.new 'test', 'a', 'b', 'c'
19
20
  @adapter.save_experiment(@experiment)
20
21
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fabes
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-07-23 00:00:00.000000000 Z
12
+ date: 2012-07-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: redis
@@ -185,6 +185,7 @@ files:
185
185
  - lib/fabes/connection_handling.rb
186
186
  - lib/fabes/experiment.rb
187
187
  - lib/fabes/helper.rb
188
+ - lib/fabes/railtie.rb
188
189
  - lib/fabes/utils.rb
189
190
  - test/helper.rb
190
191
  - test/test_abstract_adapter.rb
@@ -208,7 +209,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
208
209
  version: '0'
209
210
  segments:
210
211
  - 0
211
- hash: 4128537144808349217
212
+ hash: 3698846090476597919
212
213
  required_rubygems_version: !ruby/object:Gem::Requirement
213
214
  none: false
214
215
  requirements: