optimizely_server_side 0.0.3 → 0.0.4

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.
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