optimizely_server_side 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6398f138ed81929b7eb9057466e0bb501f21cae3
4
- data.tar.gz: abc2f4c80d0fa6dc094ed80dfc1395eb66e4685d
3
+ metadata.gz: e32298f15f7388b74f47abe8f85550d0b590d96d
4
+ data.tar.gz: babcf58d56c9adc0a8cc13458ff14b0921eed38d
5
5
  SHA512:
6
- metadata.gz: 6591c7c1872081c2748074891cb9c1f4084fae529a752d2c78ae239b78790709b9fab4bd1ded08d1195116ffffcedc5fc452d68409620b6e9a98afc595a683b8
7
- data.tar.gz: 75dd78eac9285bfd4bd988552e9fae740572af4916981ee0308e5e39abd6fcbed84b929ec355d0c752a2ca6a3ca7329b8966cc5abba42e0597899a293f118c02
6
+ metadata.gz: a948ea8f67705f498e8b9783eb6834140227a5a87944e4f3f67c499becfd774ba04a333ab9bbff82a687e285c31996232bbeb6e4ee3fe6ea70644b2a1db59ab2
7
+ data.tar.gz: c44efd2ba68bdf260569b254c88b9b69beddc90c3d90d93be507d12bc5d55fbe122ff29f0ad9fac8c7ffdea8408b5e27e56990cb511949bd9f861fe06e54a1b6
data/.gitignore CHANGED
@@ -1 +1,4 @@
1
1
  .DS_Store
2
+ optimizely_server_side-*.gem
3
+ coverage
4
+ blocky.rb
data/.travis.yml CHANGED
@@ -2,4 +2,7 @@ language: ruby
2
2
  rvm:
3
3
  - 2.2
4
4
  - 2.3.0
5
- script: bundle exec rspec spec
5
+ script: bundle exec rspec spec
6
+ addons:
7
+ code_climate:
8
+ repo_token: 3dab4dd3ef8f9baf5bf35b781aff78b4be16700dcc1db13805f34e25849d898f
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
1
  source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
+
5
+ gem "codeclimate-test-reporter", group: :test, require: nil
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- optimizely_server_side (0.0.1)
4
+ optimizely_server_side (0.0.3)
5
5
  activesupport (~> 4.2, >= 4.2.6)
6
6
  optimizely-sdk (~> 0.1.1)
7
7
 
@@ -15,9 +15,12 @@ GEM
15
15
  thread_safe (~> 0.3, >= 0.3.4)
16
16
  tzinfo (~> 1.1)
17
17
  addressable (2.3.8)
18
+ codeclimate-test-reporter (0.5.0)
19
+ simplecov (>= 0.7.1, < 1.0.0)
18
20
  crack (0.4.3)
19
21
  safe_yaml (~> 1.0.0)
20
22
  diff-lcs (1.2.5)
23
+ docile (1.1.5)
21
24
  hashdiff (0.3.0)
22
25
  httparty (0.13.7)
23
26
  json (~> 1.8)
@@ -47,6 +50,11 @@ GEM
47
50
  rspec-support (~> 3.5.0)
48
51
  rspec-support (3.5.0)
49
52
  safe_yaml (1.0.4)
53
+ simplecov (0.11.2)
54
+ docile (~> 1.1.0)
55
+ json (~> 1.8)
56
+ simplecov-html (~> 0.10.0)
57
+ simplecov-html (0.10.0)
50
58
  thread_safe (0.3.5)
51
59
  tzinfo (1.2.2)
52
60
  thread_safe (~> 0.1)
@@ -59,6 +67,7 @@ PLATFORMS
59
67
  ruby
60
68
 
61
69
  DEPENDENCIES
70
+ codeclimate-test-reporter
62
71
  optimizely_server_side!
63
72
  rspec (~> 3.5)
64
73
  webmock (~> 2.1)
data/Readme.md CHANGED
@@ -1,6 +1,8 @@
1
1
  ## Optimizely Server Side
2
2
 
3
3
  [![Code Climate](https://codeclimate.com/github/ankit8898/optimizely_config_provider/badges/gpa.svg)](https://codeclimate.com/github/ankit8898/optimizely_config_provider) [![Build Status](https://travis-ci.org/ankit8898/optimizely_server_side.svg?branch=master)](https://travis-ci.org/ankit8898/optimizely_server_side)
4
+ [![Gem Version](https://badge.fury.io/rb/optimizely_server_side.svg)](https://badge.fury.io/rb/optimizely_server_side)
5
+ [![Test Coverage](https://codeclimate.com/github/ankit8898/optimizely_config_provider/badges/coverage.svg)](https://codeclimate.com/github/ankit8898/optimizely_config_provider/coverage)
4
6
 
5
7
  ### What is Optimizely Server Side ?
6
8
 
@@ -12,19 +14,26 @@ This gem solves few things:
12
14
 
13
15
  - **Syncing AB test config across different servers when you don't want to fetch config via REST endpoint or redis/memcache store**
14
16
 
17
+ Yes, it's designed keeping performance in mind as we want to save a network overhead and a extra dependency.
18
+
15
19
  If you are using Optimizely you will be aware about the [datafile](http://developers.optimizely.com/server/reference/index.html#datafile). Once we make changes to the A/B test like change in percent distribution, start / pause a experiment this file get's updated.
16
20
 
17
- If you have 50 servers with 40 passenger / puma process these process needs to be updated. The Gem polls the config at regular interval and keeps the file cached across different process.
21
+ If you have 50 servers with 40 passenger / puma process these process needs to be updated. The Gem polls the config at regular interval and keeps the datafile cached across different process.
18
22
 
19
- The config is stored in **Memory Store** .
23
+ The config is stored in **Memory Store** . We use [Activesupport memory store](http://api.rubyonrails.org/classes/ActiveSupport/Cache/MemoryStore.html) for same.
20
24
 
21
25
  * **Some additional helpers**
22
26
 
23
27
  Some more helpers exposed that can be exposed in views (.erbs) or PORO's. It avoids duplication of few activation settings.
24
28
 
29
+ ### Architecture
30
+
31
+ ![alt text](https://github.com/ankit8898/optimizely_server_side/blob/master/docs/general_architecture.png
32
+ "Architecture")
33
+
25
34
  ### Getting Started
26
35
 
27
- Add the gem in you Gemfile
36
+ Add the gem in your Gemfile
28
37
 
29
38
  ```ruby
30
39
  gem 'optimizely_server_side'
@@ -71,7 +80,6 @@ class ApplicationController < ActionController::Base
71
80
 
72
81
  ```
73
82
 
74
-
75
83
  Now in your views or models
76
84
 
77
85
 
@@ -93,12 +101,29 @@ experiment(EXPERIMENT_KEY) do |config|
93
101
  end
94
102
  ```
95
103
 
96
- EXPERIMENT_KEY: The experiment key that you will be getting while setting up your experiment from https://app.optimizely.com.
104
+ `EXPERIMENT_KEY`: The experiment key that you will be getting while setting up your experiment from https://app.optimizely.com.
97
105
 
98
- VARIATION_ONE_KEY: Key for Variation one. This will be also set when setting up experiment
106
+ `VARIATION_ONE_KEY`: Key for Variation one. This will be also set when setting up experiment
99
107
 
100
- VARIATION_TWO_KEY: Key for Variation two. This will be also set when setting up experiment
108
+ `VARIATION_TWO_KEY`: Key for Variation two. This will be also set when setting up experiment
101
109
 
102
- VARIATION_DEFAULT_KEY: Key for default experience. This will be also set when setting up experiment
110
+ `VARIATION_DEFAULT_KEY`: Key for default experience. This will be also set when setting up experiment
103
111
 
104
112
  ![alt text](https://github.com/ankit8898/optimizely_server_side/blob/master/docs/screenshot.png "Logo Title Text 1")
113
+
114
+ ### Testing
115
+
116
+ Gem uses rspec for unit testing
117
+
118
+ ```ruby
119
+ bundle exec rspec .
120
+ ```
121
+
122
+ ```
123
+ Finished in 0.28287 seconds (files took 1.3 seconds to load)
124
+ 36 examples, 0 failures
125
+ ```
126
+
127
+ ### License
128
+
129
+ The MIT License
Binary file
@@ -6,7 +6,7 @@ require 'optimizely'
6
6
  require 'optimizely_server_side/cache'
7
7
  require 'optimizely_server_side/configuration'
8
8
  require 'optimizely_server_side/datafile_fetcher'
9
- require 'optimizely_server_side/variation'
9
+ require 'optimizely_server_side/experiment'
10
10
  require 'optimizely_server_side/optimizely_sdk'
11
11
  require 'optimizely_server_side/helpers/support'
12
12
 
@@ -11,7 +11,9 @@ module OptimizelyServerSide
11
11
  # We are sticking with Activesupprt memory store as gem is to be used with
12
12
  # Rails app for now.
13
13
  def initialize
14
- @cache_store_instance = ActiveSupport::Cache::MemoryStore.new(expires_in: OptimizelyServerSide.configuration.cache_expiry.send(:minutes))
14
+ @cache_store_instance = ActiveSupport::Cache::MemoryStore.new(
15
+ expires_in: OptimizelyServerSide.configuration.cache_expiry.send(:minutes)
16
+ )
15
17
  end
16
18
 
17
19
  class << self
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module OptimizelyServerSide
2
3
 
3
4
  class Configuration
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module OptimizelyServerSide
2
3
 
3
4
  class DatafileFetcher
@@ -5,14 +6,44 @@ module OptimizelyServerSide
5
6
  # the API source. The API can be optimizely cdn itself or
6
7
  # any other source.
7
8
 
9
+ attr_reader :content, :success
10
+
11
+ def initialize(content:, success:)
12
+ @content = content
13
+ @success = success
14
+ end
15
+
8
16
  class << self
9
17
 
10
18
  # Fetch the Config from the specified source.
11
19
  def fetch
12
- Net::HTTP.get(URI(OptimizelyServerSide.configuration.config_endpoint))
20
+ begin
21
+ response = call_optimizely_cdn
22
+ if response.is_a?(Net::HTTPSuccess)
23
+ new(content: response.body, success: true)
24
+ else
25
+ fallback
26
+ end
27
+ rescue Exception => e
28
+ fallback
29
+ end
13
30
  end
14
31
  alias_method :datafile, :fetch
15
32
 
33
+ # Gets data from Optimizely cdn
34
+ def call_optimizely_cdn
35
+ Net::HTTP.get_response(
36
+ URI(OptimizelyServerSide.configuration.config_endpoint)
37
+ )
38
+ end
39
+
40
+ def fallback
41
+ new(
42
+ content: '{"experiments": [],"version": "1","audiences": [],"dimensions": [],"groups": [],"projectId": "5960232316","accountId": "5955320306","events": [],"revision": "30"}',
43
+ success: false
44
+ )
45
+
46
+ end
16
47
  end
17
48
 
18
49
  end
@@ -0,0 +1,52 @@
1
+ module OptimizelyServerSide
2
+ class Experiment
3
+
4
+ def initialize(key)
5
+ @another_key = key
6
+ @store = {}
7
+ end
8
+
9
+ def start
10
+ yield(self)
11
+ self.compute
12
+ end
13
+
14
+
15
+ def variation_one(key, &blk)
16
+ @store[key] = blk
17
+ end
18
+
19
+ def variation_two(key, &blk)
20
+ @store[key] = blk
21
+ end
22
+
23
+ def variation_three(key, &blk)
24
+ @store[key] = blk
25
+ end
26
+
27
+ def variation_default(key, &blk)
28
+ @store[key] = blk
29
+ end
30
+
31
+ def compute
32
+ puts "---Experience selected----- #{@another_key}"
33
+ if @store[@another_key]
34
+ @store[@another_key].call
35
+ end
36
+ end
37
+
38
+ end
39
+ end
40
+ #
41
+ # a = Foo.new.start do |config|
42
+ #
43
+ # config.game_one('aa') do
44
+ # '<div> \n </div>'
45
+ # end
46
+ #
47
+ # config.game_two('bb') do
48
+ # '<div> \n kjsdkaskfsajkfjk </div>'
49
+ # end
50
+ # end
51
+ #
52
+ # p a
@@ -21,14 +21,14 @@ module OptimizelyServerSide
21
21
  # end
22
22
 
23
23
  def experiment(experiment_key, &blk)
24
- result_variation_key = optimizely_sdk_project_instance(experiment_key)
25
- variation_instance = OptimizelyServerSide::Variation.new(result_variation_key)
26
- blk.call(variation_instance)
27
- variation_instance.compute
24
+ variation_key = optimizely_sdk_project_instance(experiment_key)
25
+ OptimizelyServerSide::Experiment.new(variation_key).start(&blk)
28
26
  end
29
27
 
30
28
  def optimizely_sdk_project_instance(experiment_key)
31
- OptimizelyServerSide::OptimizelySdk.project_instance(event_dispather: MyEventDispatcher.new).activate(experiment_key, OptimizelyServerSide.configuration.visitor_id)
29
+ OptimizelyServerSide::OptimizelySdk
30
+ .project_instance(event_dispatcher: MyEventDispatcher.new)
31
+ .activate(experiment_key, OptimizelyServerSide.configuration.visitor_id)
32
32
  end
33
33
 
34
34
  end
@@ -1,16 +1,26 @@
1
+ # frozen_string_literal: true
1
2
  module OptimizelyServerSide
2
3
 
3
4
  class OptimizelySdk
4
5
 
5
- # Public method to be accessed in the application
6
- # This is the project instance and is giving
7
- # access to all the optimizely sdk methods.
8
- # Datafile
9
- def self.project_instance(options = {})
10
- Cache.fetch('optimizely_sdk_config'.freeze) do
11
- puts "Getting the configg"
12
- Optimizely::Project.new(DatafileFetcher.datafile, options[:event_dispather])
6
+ class << self
7
+
8
+ # Public method to be accessed in the application
9
+ # This is the project instance and is giving
10
+ # access to all the optimizely sdk methods.
11
+ # Datafile
12
+ def project_instance(options = {})
13
+ Optimizely::Project.new(cached_datafile,
14
+ options[:event_dispatcher])
15
+ end
16
+
17
+ def cached_datafile
18
+ Cache.fetch('optimizely_sdk_config') do
19
+ puts "*********** Getting the config ***********"
20
+ DatafileFetcher.datafile.content
21
+ end
13
22
  end
23
+
14
24
  end
15
25
 
16
26
  end
@@ -2,10 +2,10 @@ $:.push File.expand_path("../lib", __FILE__)
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'optimizely_server_side'
5
- s.version = '0.0.3'
6
- s.date = '2016-08-10'
5
+ s.version = '0.0.4'
6
+ s.date = '2016-08-13'
7
7
  s.summary = "Optimizely server side. A wrapper on top of optimizely's ruby sdk for easy caching of server side config "
8
- s.description = "Optimizely server side. A wrapper on top of optimizely's ruby sdk for easy caching of server side config and exposing few more utility helpers "
8
+ s.description = "Optimizely server side. A AB test wrapper on top of optimizely's ruby sdk for easy caching of server side config and exposing few more utility helpers. Handling of fallbacks and marking primary experiments. "
9
9
  s.authors = ["Ankit Gupta"]
10
10
  s.email = 'ankit.gupta8898@gmail.com'
11
11
  s.files = `git ls-files`.split("\n")
@@ -28,7 +28,7 @@ RSpec.describe OptimizelyServerSide::Cache do
28
28
  it 'should return the config from API and cache it' do
29
29
  expect(
30
30
  described_class.fetch('key') do
31
- JSON.parse(OptimizelyServerSide::DatafileFetcher.datafile, symbolize_names: true)
31
+ JSON.parse(OptimizelyServerSide::DatafileFetcher.datafile.content, symbolize_names: true)
32
32
  end
33
33
  ).to eq(
34
34
  {
@@ -4,18 +4,39 @@ RSpec.describe OptimizelyServerSide::DatafileFetcher do
4
4
 
5
5
  describe '#fetch' do
6
6
 
7
- before do
8
- stub_request(:get, "https://cdn.optimizely.com/json/5960232316.json")
9
- .to_return(body: '{"experiments": [{"status": "running"}]}',status: 200)
10
- end
7
+ context 'when 200 response' do
8
+ before do
9
+ stub_request(:get, "https://cdn.optimizely.com/json/5960232316.json")
10
+ .to_return(body: '{"experiments": [{"status": "running"}]}',status: 200)
11
+ end
12
+
13
+ it 'should fetch the config' do
14
+ expect(described_class.fetch.content).to eq('{"experiments": [{"status": "running"}]}')
15
+ end
16
+
17
+
18
+ it 'should return stringified datafile' do
19
+ expect(described_class.datafile.content).to eq('{"experiments": [{"status": "running"}]}')
20
+ end
11
21
 
12
- it 'should fetch the config' do
13
- expect(described_class.fetch).to eq('{"experiments": [{"status": "running"}]}')
14
22
  end
15
23
 
16
24
 
17
- it 'should return stringified datafile' do
18
- expect(described_class.datafile).to eq('{"experiments": [{"status": "running"}]}')
25
+ context 'when 500 response' do
26
+ before do
27
+ stub_request(:get, "https://cdn.optimizely.com/json/5960232316.json")
28
+ .to_return(body: '{"experiments": [{"status": "running"}]}',status: 500)
29
+ end
30
+
31
+ it 'should fetch the config' do
32
+ expect(described_class.fetch.content).to eq('{"experiments": [],"version": "1","audiences": [],"dimensions": [],"groups": [],"projectId": "5960232316","accountId": "5955320306","events": [],"revision": "30"}')
33
+ end
34
+
35
+
36
+ it 'should return stringified datafile' do
37
+ expect(described_class.datafile.content).to eq('{"experiments": [],"version": "1","audiences": [],"dimensions": [],"groups": [],"projectId": "5960232316","accountId": "5955320306","events": [],"revision": "30"}')
38
+ end
39
+
19
40
  end
20
41
 
21
42
  end
@@ -0,0 +1,138 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe OptimizelyServerSide::Experiment do
4
+
5
+ subject { OptimizelyServerSide::Experiment.new(variation_key = 'variation_key_a') }
6
+
7
+
8
+ describe '#compute' do
9
+
10
+ before do
11
+
12
+ subject.variation_one('variation_key_a') do
13
+ 'experience a'
14
+ end
15
+
16
+ subject.variation_two('variation_key_b') do
17
+ 'experience b'
18
+ end
19
+
20
+ end
21
+
22
+ context 'when variation_key is present' do
23
+
24
+ it 'should result variation b' do
25
+ expect(subject.compute).to eq('experience a')
26
+ end
27
+
28
+ end
29
+
30
+
31
+ context 'when variation_key is not present' do
32
+ subject { OptimizelyServerSide::Experiment.new(variation_key = '') }
33
+
34
+ it 'should be nil' do
35
+ expect(subject.compute).to be_nil
36
+ end
37
+ end
38
+
39
+
40
+ end
41
+
42
+ describe '#variation_one' do
43
+
44
+ let(:blk) { Proc.new { 'Hello!'} }
45
+
46
+ it 'returns a block passed' do
47
+ expect(subject.variation_one('foo', &blk)).to eq(blk)
48
+ end
49
+ end
50
+
51
+
52
+ describe '#variation_two' do
53
+
54
+ let(:blk) { -> {OpenStruct.new } }
55
+
56
+ it 'returns a block passed' do
57
+ expect(subject.variation_two('foo', &blk)).to eq(blk)
58
+ end
59
+ end
60
+
61
+ describe '#variation_three' do
62
+
63
+ let(:blk) { Proc.new { 'Hello!'} }
64
+
65
+ it 'returns a block passed' do
66
+ expect(subject.variation_three('foo', &blk)).to eq(blk)
67
+ end
68
+ end
69
+
70
+ describe '#store' do
71
+
72
+ context 'key accepts regular strings' do
73
+
74
+ let(:string_lambda) { -> {'I am a variation' } }
75
+
76
+ before do
77
+ subject.variation_one('foo', &string_lambda)
78
+ end
79
+
80
+ it 'has value as string' do
81
+ expect(subject.instance_variable_get(:@store)).to eq({'foo' => string_lambda})
82
+ end
83
+
84
+ end
85
+
86
+
87
+ context 'key accepts blocks / proc' do
88
+
89
+ let(:some_method) { Proc.new {|n| n*2 } }
90
+
91
+ before do
92
+ subject.variation_one('foo', &some_method)
93
+ end
94
+
95
+ it 'has value as proc' do
96
+ expect(subject.instance_variable_get(:@store)).to eq({'foo' => some_method})
97
+ end
98
+
99
+ end
100
+
101
+ context 'key accepts string, html or blocks / proc' do
102
+
103
+ let(:some_method) { Proc.new {|n| n*2 } }
104
+
105
+ let(:some_html_block) do
106
+ -> {'<!DOCTYPE html>
107
+ <html>
108
+ <head>
109
+ <title>Page Title</title>
110
+ </head>
111
+ <body>
112
+
113
+ <h1>This is a Heading</h1>
114
+ <p>This is a paragraph.</p>
115
+
116
+ </body>
117
+ </html>
118
+ '
119
+ }
120
+ end
121
+
122
+ let(:string_blk) { -> { 'Hello!'} }
123
+
124
+ before do
125
+ subject.variation_one('foo', &some_method)
126
+
127
+ subject.variation_two('foo_two', &some_html_block)
128
+
129
+ subject.variation_three('foo_three', &string_blk)
130
+ end
131
+
132
+ it 'has value as proc' do
133
+ expect(subject.instance_variable_get(:@store)).to eq({'foo' => some_method, 'foo_two' => some_html_block, 'foo_three' => string_blk})
134
+ end
135
+
136
+ end
137
+ end
138
+ end
@@ -2,6 +2,12 @@ require 'spec_helper'
2
2
 
3
3
  RSpec.describe OptimizelyServerSide::Support do
4
4
 
5
+ class MyEventDispatcher
6
+
7
+ def dispatch_event(url,params)
8
+ puts "Do nothing with #{url} and #{params}"
9
+ end
10
+ end
5
11
  class FakeKlass
6
12
 
7
13
  include OptimizelyServerSide::Support
@@ -24,14 +30,44 @@ RSpec.describe OptimizelyServerSide::Support do
24
30
  end
25
31
 
26
32
 
27
- context '#experiment' do
33
+ describe '#experiment' do
28
34
 
29
35
  subject { FakeKlass.new }
30
36
 
31
- before do
32
- allow(subject).to receive(:optimizely_sdk_project_instance).and_return('variation_one')
37
+ context 'everything is good' do
38
+
39
+
40
+ before do
41
+ allow(subject).to receive(:optimizely_sdk_project_instance).and_return('variation_one')
42
+ end
43
+
44
+ it { expect(subject.some_klass_method).to eq('Experience one')}
33
45
  end
34
46
 
35
- it { expect(subject.some_klass_method).to eq('Experience one')}
47
+
48
+ context 'when a fatal error has happened' do
49
+
50
+ let(:response) do
51
+ '{
52
+ "experiments": [],
53
+ "version": "1",
54
+ "audiences": [],
55
+ "dimensions": [],
56
+ "groups": [],
57
+ "projectId": "5960232316",
58
+ "accountId": "5955320306",
59
+ "events": [],
60
+ "revision": "30"
61
+ }'
62
+ end
63
+
64
+ before do
65
+ stub_request(:get, "https://cdn.optimizely.com/json/5960232316.json")
66
+ .to_return(body: response, status: 500)
67
+ end
68
+
69
+
70
+ it { expect(subject.some_klass_method).to be_nil }
71
+ end
36
72
  end
37
73
  end
@@ -55,21 +55,3 @@ RSpec.describe OptimizelyServerSide do
55
55
 
56
56
  end
57
57
  end
58
-
59
- def foo
60
- experiment(EXPERIMENT_KEY) do |config|
61
-
62
- config.variation_one(VARIATION_ONE_KEY) do
63
- # Code for experience one. it can be html or a ruby code
64
- end
65
-
66
- config.variation_two(VARIATION_TWO_KEY) do
67
- # Code for experience two. it can be html or a ruby code
68
- end
69
-
70
- config.variation_default(variation_default_KEY) do
71
- # Code for experience default. it can be html or a ruby code
72
- end
73
-
74
- end
75
- end
data/spec/spec_helper.rb CHANGED
@@ -1,9 +1,12 @@
1
+ require "codeclimate-test-reporter"
2
+ CodeClimate::TestReporter.start
3
+
1
4
  require 'bundler/setup'
2
5
  require 'webmock/rspec'
3
6
  Bundler.setup
4
7
 
5
8
  require 'optimizely_server_side'
6
-
9
+ WebMock.disable_net_connect!(allow: 'codeclimate.com')
7
10
  RSpec.configure do |config|
8
11
  # some (optional) config here
9
12
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: optimizely_server_side
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ankit Gupta
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-10 00:00:00.000000000 Z
11
+ date: 2016-08-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -72,8 +72,9 @@ dependencies:
72
72
  - - ">="
73
73
  - !ruby/object:Gem::Version
74
74
  version: 4.2.6
75
- description: 'Optimizely server side. A wrapper on top of optimizely''s ruby sdk for
76
- easy caching of server side config and exposing few more utility helpers '
75
+ description: 'Optimizely server side. A AB test wrapper on top of optimizely''s ruby
76
+ sdk for easy caching of server side config and exposing few more utility helpers. Handling
77
+ of fallbacks and marking primary experiments. '
77
78
  email: ankit.gupta8898@gmail.com
78
79
  executables: []
79
80
  extensions: []
@@ -85,21 +86,23 @@ files:
85
86
  - Gemfile
86
87
  - Gemfile.lock
87
88
  - Readme.md
89
+ - blocky.rb
90
+ - docs/general_architecture.png
88
91
  - docs/screenshot.png
89
92
  - lib/optimizely_server_side.rb
90
93
  - lib/optimizely_server_side/cache.rb
91
94
  - lib/optimizely_server_side/configuration.rb
92
95
  - lib/optimizely_server_side/datafile_fetcher.rb
96
+ - lib/optimizely_server_side/experiment.rb
93
97
  - lib/optimizely_server_side/helpers/support.rb
94
98
  - lib/optimizely_server_side/optimizely_sdk.rb
95
- - lib/optimizely_server_side/variation.rb
96
99
  - optimizely_server_side.gemspec
97
100
  - spec/optimizely_server_side/cache_spec.rb
98
101
  - spec/optimizely_server_side/configuration_spec.rb
99
102
  - spec/optimizely_server_side/datafile_fetcher_spec.rb
103
+ - spec/optimizely_server_side/experiment_spec.rb
100
104
  - spec/optimizely_server_side/helpers/support_spec.rb
101
105
  - spec/optimizely_server_side/optimizely_sdk_spec.rb
102
- - spec/optimizely_server_side/variation_spec.rb
103
106
  - spec/optimizely_server_side_spec.rb
104
107
  - spec/spec_helper.rb
105
108
  homepage: https://github.com/ankit8898/optimizely_server_side
@@ -131,8 +134,8 @@ test_files:
131
134
  - spec/optimizely_server_side/cache_spec.rb
132
135
  - spec/optimizely_server_side/configuration_spec.rb
133
136
  - spec/optimizely_server_side/datafile_fetcher_spec.rb
137
+ - spec/optimizely_server_side/experiment_spec.rb
134
138
  - spec/optimizely_server_side/helpers/support_spec.rb
135
139
  - spec/optimizely_server_side/optimizely_sdk_spec.rb
136
- - spec/optimizely_server_side/variation_spec.rb
137
140
  - spec/optimizely_server_side_spec.rb
138
141
  - spec/spec_helper.rb
@@ -1,38 +0,0 @@
1
- module OptimizelyServerSide
2
-
3
- class Variation
4
-
5
- attr_reader :hsh
6
-
7
- def initialize(variation_key)
8
- @variation_key = variation_key
9
- @hsh = {}
10
- end
11
-
12
- # Variation one of experiment
13
- def variation_one(key)
14
- @hsh[key] = yield
15
- end
16
-
17
- # Variation two of experiment
18
- def variation_two(key)
19
- @hsh[key] = yield
20
- end
21
-
22
- def variation_default(key)
23
- @hsh[key] = yield
24
- end
25
-
26
- # Variation three of experiment
27
- def variation_three(key)
28
- @hsh[key] = yield
29
- end
30
-
31
- # Select which variation to be picked up
32
- def compute
33
- @hsh.select do |key,value|
34
- key == @variation_key
35
- end.values[0]
36
- end
37
- end
38
- end
@@ -1,137 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe OptimizelyServerSide::Variation do
4
-
5
- subject { OptimizelyServerSide::Variation.new(variation_key = 'variation_key_a') }
6
-
7
-
8
- describe '#compute' do
9
-
10
-
11
- before do
12
-
13
- subject.variation_one('variation_key_a') do
14
- 'experience a'
15
- end
16
-
17
- subject.variation_two('variation_key_b') do
18
- 'experience b'
19
- end
20
-
21
- end
22
-
23
- it 'should result variation b' do
24
- expect(subject.compute).to eq('experience a')
25
- end
26
- end
27
-
28
-
29
- ['variation_one','variation_two','variation_three','variation_default'].each do |variation|
30
-
31
- describe "#{variation}" do
32
-
33
- context 'it accepts regular strings' do
34
-
35
- it do
36
- expect(subject.send(variation,'foo') do
37
- 'Hello!'
38
- end).to eq('Hello!')
39
- end
40
-
41
- end
42
-
43
-
44
- context 'it accepts a block' do
45
-
46
- let(:some_block) do
47
- -> { 'something'}
48
- end
49
-
50
- it do
51
- expect(subject.send(variation,'foo') do
52
- some_block
53
- end).to eq(some_block)
54
- end
55
-
56
- end
57
-
58
- end
59
-
60
-
61
- describe '#hsh' do
62
-
63
- context 'key accepts regular strings' do
64
-
65
- let(:string) { 'I am a variation' }
66
-
67
- before do
68
- subject.variation_one('foo') do
69
- string
70
- end
71
- end
72
-
73
- it 'has value as string' do
74
- expect(subject.hsh).to eq({'foo' => string})
75
- end
76
-
77
- end
78
-
79
-
80
- context 'key accepts blocks / proc' do
81
-
82
- let(:proc) { Proc.new {|n| n*2 } }
83
-
84
- before do
85
- subject.variation_one('foo') do
86
- proc
87
- end
88
- end
89
-
90
- it 'has value as proc' do
91
- expect(subject.hsh).to eq({'foo' => proc})
92
- end
93
-
94
- end
95
-
96
- context 'key accepts string, html or blocks / proc' do
97
-
98
- let(:proc) { Proc.new {|n| n*2 } }
99
- let(:html) do
100
- '<!DOCTYPE html>
101
- <html>
102
- <head>
103
- <title>Page Title</title>
104
- </head>
105
- <body>
106
-
107
- <h1>This is a Heading</h1>
108
- <p>This is a paragraph.</p>
109
-
110
- </body>
111
- </html>
112
- '
113
- end
114
- let(:string) { 'Hello!'}
115
-
116
- before do
117
- subject.variation_one('foo') do
118
- proc
119
- end
120
-
121
- subject.variation_two('foo_two') do
122
- html
123
- end
124
-
125
- subject.variation_three('foo_three') do
126
- string
127
- end
128
- end
129
-
130
- it 'has value as proc' do
131
- expect(subject.hsh).to eq({'foo' => proc, 'foo_two' => html, 'foo_three' => string})
132
- end
133
-
134
- end
135
- end
136
- end
137
- end