optimizely_server_side 0.0.5 → 0.0.6
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 +4 -4
 - data/.rspec +1 -1
 - data/Gemfile.lock +4 -1
 - data/Readme.md +76 -24
 - data/lib/optimizely_server_side.rb +1 -0
 - data/lib/optimizely_server_side/datafile_fetcher.rb +2 -1
 - data/lib/optimizely_server_side/experiment.rb +40 -16
 - data/lib/optimizely_server_side/helpers/support.rb +1 -2
 - data/lib/optimizely_server_side/variation.rb +23 -0
 - data/optimizely_server_side.gemspec +3 -2
 - data/spec/optimizely_server_side/experiment_spec.rb +164 -16
 - data/spec/optimizely_server_side/variation_spec.rb +75 -0
 - data/spec/spec_helper.rb +2 -0
 - metadata +27 -4
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA1:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 52a8ee884cb6db767b45acb026984cb413f77dca
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: f674f904ce523f6003db14456367a47df57b48d2
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 42058be44f0bd1cc8ce1a16b6aae1e7aba342d558a4cc5f8dacf13a97a03f5c3751126cf4ba10839cc89a0701026f32213af3e777345051aa3650c22dc851068
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 115f4e2b2ee276c8eb29b5160fd83074fc12b25aa01f5fcdaab5eb3400c7fcafad738f7fce52781095a96855f218aa6207dc0c7aa63c22567ee0aed0e5614b2a
         
     | 
    
        data/.rspec
    CHANGED
    
    | 
         @@ -1,2 +1,2 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            --format  
     | 
| 
      
 1 
     | 
    
         
            +
            --format progress
         
     | 
| 
       2 
2 
     | 
    
         
             
            --color
         
     | 
    
        data/Gemfile.lock
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            PATH
         
     | 
| 
       2 
2 
     | 
    
         
             
              remote: .
         
     | 
| 
       3 
3 
     | 
    
         
             
              specs:
         
     | 
| 
       4 
     | 
    
         
            -
                optimizely_server_side (0.0. 
     | 
| 
      
 4 
     | 
    
         
            +
                optimizely_server_side (0.0.6)
         
     | 
| 
       5 
5 
     | 
    
         
             
                  activesupport (~> 4.2, >= 4.2.6)
         
     | 
| 
       6 
6 
     | 
    
         
             
                  optimizely-sdk (~> 0.1.1)
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
         @@ -40,6 +40,8 @@ GEM 
     | 
|
| 
       40 
40 
     | 
    
         
             
                  rspec-core (~> 3.5.0)
         
     | 
| 
       41 
41 
     | 
    
         
             
                  rspec-expectations (~> 3.5.0)
         
     | 
| 
       42 
42 
     | 
    
         
             
                  rspec-mocks (~> 3.5.0)
         
     | 
| 
      
 43 
     | 
    
         
            +
                rspec-collection_matchers (1.1.2)
         
     | 
| 
      
 44 
     | 
    
         
            +
                  rspec-expectations (>= 2.99.0.beta1)
         
     | 
| 
       43 
45 
     | 
    
         
             
                rspec-core (3.5.2)
         
     | 
| 
       44 
46 
     | 
    
         
             
                  rspec-support (~> 3.5.0)
         
     | 
| 
       45 
47 
     | 
    
         
             
                rspec-expectations (3.5.0)
         
     | 
| 
         @@ -70,6 +72,7 @@ DEPENDENCIES 
     | 
|
| 
       70 
72 
     | 
    
         
             
              codeclimate-test-reporter
         
     | 
| 
       71 
73 
     | 
    
         
             
              optimizely_server_side!
         
     | 
| 
       72 
74 
     | 
    
         
             
              rspec (~> 3.5)
         
     | 
| 
      
 75 
     | 
    
         
            +
              rspec-collection_matchers (~> 1.1, >= 1.1.2)
         
     | 
| 
       73 
76 
     | 
    
         
             
              webmock (~> 2.1)
         
     | 
| 
       74 
77 
     | 
    
         | 
| 
       75 
78 
     | 
    
         
             
            BUNDLED WITH
         
     | 
    
        data/Readme.md
    CHANGED
    
    | 
         @@ -12,19 +12,20 @@ This is a wrapper on top of [Optimizely's](https://app.optimizely.com/projects) 
     | 
|
| 
       12 
12 
     | 
    
         | 
| 
       13 
13 
     | 
    
         
             
            This gem solves few things:
         
     | 
| 
       14 
14 
     | 
    
         | 
| 
       15 
     | 
    
         
            -
             - **Syncing  
     | 
| 
      
 15 
     | 
    
         
            +
             - **Syncing A/B test config across different servers when you don't want to fetch config via REST endpoint or redis/memcache store**
         
     | 
| 
       16 
16 
     | 
    
         | 
| 
       17 
17 
     | 
    
         
             
              Yes, it's designed keeping performance in mind as we want to save a network overhead and a extra dependency.
         
     | 
| 
       18 
18 
     | 
    
         | 
| 
       19 
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.
         
     | 
| 
       20 
20 
     | 
    
         | 
| 
       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.
         
     | 
| 
      
 21 
     | 
    
         
            +
              If you have 50 servers with 40 passenger / puma process each these process needs to be updated.  The Gem polls the config at regular interval and keeps the datafile cached across different process.
         
     | 
| 
       22 
22 
     | 
    
         | 
| 
       23 
23 
     | 
    
         
             
              The config is stored in **Memory Store** . We use [Activesupport memory store](http://api.rubyonrails.org/classes/ActiveSupport/Cache/MemoryStore.html) for same.
         
     | 
| 
       24 
24 
     | 
    
         | 
| 
       25 
     | 
    
         
            -
            * ** 
     | 
| 
      
 25 
     | 
    
         
            +
            * **Helper methods to better handle test and variations and handling fallbacks and experiment pause**
         
     | 
| 
       26 
26 
     | 
    
         | 
| 
       27 
     | 
    
         
            -
               
     | 
| 
      
 27 
     | 
    
         
            +
              Optimizely ruby sdk provides us way to know which variation to show. But what happens when the experiment is paused ? Or there is a error happening in config.  
         
     | 
| 
      
 28 
     | 
    
         
            +
              More details about this in below section of experiment config.
         
     | 
| 
       28 
29 
     | 
    
         | 
| 
       29 
30 
     | 
    
         
             
            ### Architecture
         
     | 
| 
       30 
31 
     | 
    
         | 
| 
         @@ -58,12 +59,13 @@ end 
     | 
|
| 
       58 
59 
     | 
    
         
             
            `PROJECT_ID` is a id of your  server side project at https://app.optimizely.com .
         
     | 
| 
       59 
60 
     | 
    
         | 
| 
       60 
61 
     | 
    
         | 
| 
       61 
     | 
    
         
            -
            Optimizely needs a visitor_id to track the unique user and server a constant experience.  
         
     | 
| 
      
 62 
     | 
    
         
            +
            Optimizely needs a `visitor_id` to track the unique user and server a constant experience.  
         
     | 
| 
       62 
63 
     | 
    
         | 
| 
       63 
64 
     | 
    
         
             
            In your Application controller
         
     | 
| 
       64 
65 
     | 
    
         | 
| 
       65 
66 
     | 
    
         
             
            ```ruby
         
     | 
| 
       66 
67 
     | 
    
         
             
            class ApplicationController < ActionController::Base
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
       67 
69 
     | 
    
         
             
              include OptimizelyServerSide::Support
         
     | 
| 
       68 
70 
     | 
    
         | 
| 
       69 
71 
     | 
    
         
             
              before_action :set_visitor_id
         
     | 
| 
         @@ -80,48 +82,98 @@ class ApplicationController < ActionController::Base 
     | 
|
| 
       80 
82 
     | 
    
         | 
| 
       81 
83 
     | 
    
         
             
            ```
         
     | 
| 
       82 
84 
     | 
    
         | 
| 
       83 
     | 
    
         
            -
             
     | 
| 
      
 85 
     | 
    
         
            +
            ### Example usage
         
     | 
| 
       84 
86 
     | 
    
         | 
| 
      
 87 
     | 
    
         
            +
            #### In your html.erb
         
     | 
| 
       85 
88 
     | 
    
         | 
| 
       86 
89 
     | 
    
         
             
            ```ruby
         
     | 
| 
       87 
     | 
    
         
            -
             
     | 
| 
      
 90 
     | 
    
         
            +
            # in any app/view/foo.html.erb
         
     | 
| 
      
 91 
     | 
    
         
            +
            <% experiment(EXPERIMENT_KEY) do |config| %>
         
     | 
| 
      
 92 
     | 
    
         
            +
              <% config.variation_one(VARIATION_ONE_KEY) do %>
         
     | 
| 
      
 93 
     | 
    
         
            +
                <%= render partial: 'variation_one_experience'    
         
     | 
| 
      
 94 
     | 
    
         
            +
              <% end %>
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
              <% config.variation_default(VARIATION_DEFAULT_KEY, primary: true) do %>
         
     | 
| 
      
 97 
     | 
    
         
            +
                <%= render partial: 'variation_default_experience'    
         
     | 
| 
      
 98 
     | 
    
         
            +
              <% end %>
         
     | 
| 
      
 99 
     | 
    
         
            +
            <% end %>
         
     | 
| 
      
 100 
     | 
    
         
            +
            ```
         
     | 
| 
       88 
101 
     | 
    
         | 
| 
       89 
     | 
    
         
            -
             
     | 
| 
       90 
     | 
    
         
            -
                # Code for experience one. it can be html or a ruby code
         
     | 
| 
       91 
     | 
    
         
            -
              end
         
     | 
| 
      
 102 
     | 
    
         
            +
            #### In your model or any PORO
         
     | 
| 
       92 
103 
     | 
    
         | 
| 
       93 
     | 
    
         
            -
             
     | 
| 
       94 
     | 
    
         
            -
             
     | 
| 
       95 
     | 
    
         
            -
             
     | 
| 
      
 104 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 105 
     | 
    
         
            +
            class Foo
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
      
 107 
     | 
    
         
            +
              include OptimizelyServerSide::Support
         
     | 
| 
       96 
108 
     | 
    
         | 
| 
       97 
     | 
    
         
            -
              config.variation_default(VARIATION_DEFAULT_KEY) do
         
     | 
| 
       98 
     | 
    
         
            -
                # Code for experience default. it can be html or a ruby code
         
     | 
| 
       99 
     | 
    
         
            -
              end
         
     | 
| 
       100 
109 
     | 
    
         | 
| 
      
 110 
     | 
    
         
            +
              # This method is responsible from getting data from
         
     | 
| 
      
 111 
     | 
    
         
            +
              # any other rest endpoint.
         
     | 
| 
      
 112 
     | 
    
         
            +
              # Suppose you are doing a AB test on a new endpoint / data source.
         
     | 
| 
      
 113 
     | 
    
         
            +
              def get_me_some_data
         
     | 
| 
      
 114 
     | 
    
         
            +
                data = experiment(EXPERIMENT_KEY) do |config|
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
                  config.variation_one(VARIATION_ONE_KEY) do
         
     | 
| 
      
 117 
     | 
    
         
            +
                    HTTParty.get('http://from_source_a.com/users')
         
     | 
| 
      
 118 
     | 
    
         
            +
                  end
         
     | 
| 
      
 119 
     | 
    
         
            +
             
     | 
| 
      
 120 
     | 
    
         
            +
                  config.variation_default(VARIATION_TWO_KEY, primary: true) do
         
     | 
| 
      
 121 
     | 
    
         
            +
                    HTTParty.get('http://from_source_b.com/users')
         
     | 
| 
      
 122 
     | 
    
         
            +
                  end
         
     | 
| 
      
 123 
     | 
    
         
            +
                end
         
     | 
| 
      
 124 
     | 
    
         
            +
             
     | 
| 
      
 125 
     | 
    
         
            +
              end
         
     | 
| 
       101 
126 
     | 
    
         
             
            end
         
     | 
| 
       102 
127 
     | 
    
         
             
            ```
         
     | 
| 
       103 
128 
     | 
    
         | 
| 
       104 
     | 
    
         
            -
             
     | 
| 
      
 129 
     | 
    
         
            +
            In the above examples:
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
            `EXPERIMENT_KEY`: When you will set your experiment this key will be set up that time at https://app.optimizely.com.
         
     | 
| 
       105 
132 
     | 
    
         | 
| 
       106 
     | 
    
         
            -
            `VARIATION_ONE_KEY`: Key for Variation one. This will be also set when setting up experiment
         
     | 
| 
      
 133 
     | 
    
         
            +
            `VARIATION_ONE_KEY`: Key for Variation one. This will be also set when setting up experiment.
         
     | 
| 
       107 
134 
     | 
    
         | 
| 
       108 
     | 
    
         
            -
            `VARIATION_TWO_KEY`: Key for Variation two. This will be also set when setting up experiment
         
     | 
| 
      
 135 
     | 
    
         
            +
            `VARIATION_TWO_KEY`: Key for Variation two. This will be also set when setting up experiment.
         
     | 
| 
       109 
136 
     | 
    
         | 
| 
       110 
137 
     | 
    
         
             
            `VARIATION_DEFAULT_KEY`: Key for default experience. This will be also set when setting up experiment
         
     | 
| 
       111 
138 
     | 
    
         | 
| 
      
 139 
     | 
    
         
            +
            `primary: true` : If you see above some variations are marked with `primary: true`. This enables handling the fallback capabilities of optimizely_server_side. If there is any error pulling datafile or experiment is paused the `primary` experience is served.  Not setting primary won't give any experience during fallback times.  We encourage setting it up.
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
       112 
141 
     | 
    
         
             
            
         
     | 
| 
       113 
142 
     | 
    
         | 
| 
       114 
     | 
    
         
            -
            ### Testing
         
     | 
| 
       115 
143 
     | 
    
         | 
| 
       116 
     | 
    
         
            -
             
     | 
| 
      
 144 
     | 
    
         
            +
            ### Instrumentation
         
     | 
| 
      
 145 
     | 
    
         
            +
             
     | 
| 
      
 146 
     | 
    
         
            +
            This is a trial feature and may or maynot exist in future version.
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
      
 148 
     | 
    
         
            +
            We have [ActiveSupport::Notifications](http://api.rubyonrails.org/classes/ActiveSupport/Notifications.html) hooked up for few places which are worth monitoring.
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
             
     | 
| 
      
 151 
     | 
    
         
            +
            * When the datafile is fetched from cdn. In your application you can subscribe via below. This helps to monitor the time it takes from CDN fetch
         
     | 
| 
       117 
152 
     | 
    
         | 
| 
       118 
153 
     | 
    
         
             
            ```ruby
         
     | 
| 
       119 
     | 
    
         
            -
             
     | 
| 
      
 154 
     | 
    
         
            +
            ActiveSupport::Notifications.subscribe "oss.call_optimizely_cdn" do |name, started, finished, unique_id, data|
         
     | 
| 
      
 155 
     | 
    
         
            +
              Rails.logger.info "GET Datafile from Optimizely CDN in #{(finished - started) * 1000} ms"
         
     | 
| 
      
 156 
     | 
    
         
            +
            end
         
     | 
| 
       120 
157 
     | 
    
         
             
            ```
         
     | 
| 
      
 158 
     | 
    
         
            +
            * Which variation is being served currently. In your application you can subscribe via below
         
     | 
| 
      
 159 
     | 
    
         
            +
             
     | 
| 
      
 160 
     | 
    
         
            +
            ```ruby
         
     | 
| 
       121 
161 
     | 
    
         | 
| 
      
 162 
     | 
    
         
            +
            ActiveSupport::Notifications.subscribe "oss.variation" do |name, started, finished, unique_id, data|
         
     | 
| 
      
 163 
     | 
    
         
            +
              Rails.logger.info "GET Variation from OSS in #{(finished - started) * 1000} ms with variation key #{data[:variation]}"
         
     | 
| 
      
 164 
     | 
    
         
            +
            end
         
     | 
| 
       122 
165 
     | 
    
         
             
            ```
         
     | 
| 
       123 
     | 
    
         
            -
             
     | 
| 
       124 
     | 
    
         
            -
             
     | 
| 
      
 166 
     | 
    
         
            +
            ### Testing
         
     | 
| 
      
 167 
     | 
    
         
            +
             
     | 
| 
      
 168 
     | 
    
         
            +
            Gem uses rspec for unit testing
         
     | 
| 
      
 169 
     | 
    
         
            +
             
     | 
| 
      
 170 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 171 
     | 
    
         
            +
            $~/D/p/w/optimizely_server_side> rspec .
         
     | 
| 
      
 172 
     | 
    
         
            +
            ......................................................
         
     | 
| 
      
 173 
     | 
    
         
            +
             
     | 
| 
      
 174 
     | 
    
         
            +
            Finished in 0.12234 seconds (files took 0.5512 seconds to load)
         
     | 
| 
      
 175 
     | 
    
         
            +
            54 examples, 0 failures
         
     | 
| 
      
 176 
     | 
    
         
            +
             
     | 
| 
       125 
177 
     | 
    
         
             
            ```
         
     | 
| 
       126 
178 
     | 
    
         | 
| 
       127 
179 
     | 
    
         
             
            ### License
         
     | 
| 
         @@ -8,6 +8,7 @@ require 'optimizely_server_side/configuration' 
     | 
|
| 
       8 
8 
     | 
    
         
             
            require 'optimizely_server_side/datafile_fetcher'
         
     | 
| 
       9 
9 
     | 
    
         
             
            require 'optimizely_server_side/experiment'
         
     | 
| 
       10 
10 
     | 
    
         
             
            require 'optimizely_server_side/optimizely_sdk'
         
     | 
| 
      
 11 
     | 
    
         
            +
            require 'optimizely_server_side/variation'
         
     | 
| 
       11 
12 
     | 
    
         
             
            require 'optimizely_server_side/helpers/support'
         
     | 
| 
       12 
13 
     | 
    
         | 
| 
       13 
14 
     | 
    
         
             
            module OptimizelyServerSide
         
     | 
| 
         @@ -8,7 +8,7 @@ module OptimizelyServerSide 
     | 
|
| 
       8 
8 
     | 
    
         | 
| 
       9 
9 
     | 
    
         
             
                attr_reader :content, :success
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
       11 
     | 
    
         
            -
                def initialize(content 
     | 
| 
      
 11 
     | 
    
         
            +
                def initialize(content: nil, success: false)
         
     | 
| 
       12 
12 
     | 
    
         
             
                  @content = content
         
     | 
| 
       13 
13 
     | 
    
         
             
                  @success = success
         
     | 
| 
       14 
14 
     | 
    
         
             
                end
         
     | 
| 
         @@ -16,6 +16,7 @@ module OptimizelyServerSide 
     | 
|
| 
       16 
16 
     | 
    
         
             
                class << self
         
     | 
| 
       17 
17 
     | 
    
         | 
| 
       18 
18 
     | 
    
         
             
                  # Fetch the Config from the specified source.
         
     | 
| 
      
 19 
     | 
    
         
            +
                  # Incase of any error or exception we goto the fallback data
         
     | 
| 
       19 
20 
     | 
    
         
             
                  def fetch
         
     | 
| 
       20 
21 
     | 
    
         
             
                    begin
         
     | 
| 
       21 
22 
     | 
    
         
             
                      response = call_optimizely_cdn
         
     | 
| 
         @@ -2,36 +2,60 @@ module OptimizelyServerSide 
     | 
|
| 
       2 
2 
     | 
    
         
             
              class Experiment
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
4 
     | 
    
         
             
                def initialize(key)
         
     | 
| 
       5 
     | 
    
         
            -
                  @ 
     | 
| 
       6 
     | 
    
         
            -
                  @ 
     | 
| 
      
 5 
     | 
    
         
            +
                  @selected_variation_key = key
         
     | 
| 
      
 6 
     | 
    
         
            +
                  @variations             = []
         
     | 
| 
       7 
7 
     | 
    
         
             
                end
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
      
 9 
     | 
    
         
            +
                # Starts the experiment
         
     | 
| 
       9 
10 
     | 
    
         
             
                def start
         
     | 
| 
       10 
11 
     | 
    
         
             
                  yield(self)
         
     | 
| 
       11 
     | 
    
         
            -
                  self. 
     | 
| 
      
 12 
     | 
    
         
            +
                  self.applicable_variation
         
     | 
| 
       12 
13 
     | 
    
         
             
                end
         
     | 
| 
       13 
14 
     | 
    
         | 
| 
       14 
     | 
    
         
            -
                 
     | 
| 
       15 
     | 
    
         
            -
                   
     | 
| 
      
 15 
     | 
    
         
            +
                [
         
     | 
| 
      
 16 
     | 
    
         
            +
                  :variation_one,
         
     | 
| 
      
 17 
     | 
    
         
            +
                  :variation_two,
         
     | 
| 
      
 18 
     | 
    
         
            +
                  :variation_three,
         
     | 
| 
      
 19 
     | 
    
         
            +
                  :variation_default,
         
     | 
| 
      
 20 
     | 
    
         
            +
                ].each do |variation|
         
     | 
| 
      
 21 
     | 
    
         
            +
                  define_method(variation) do |key, opts={}, &blk|  # def variation_one(key, opts = {}, &blk)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    add_variation(key, opts, &blk)                  #   add_variation(key, opts, &blk)
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end                                               # end
         
     | 
| 
       16 
24 
     | 
    
         
             
                end
         
     | 
| 
       17 
25 
     | 
    
         | 
| 
       18 
     | 
    
         
            -
                 
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
      
 26 
     | 
    
         
            +
                # Selects and calls the variation which is applicable
         
     | 
| 
      
 27 
     | 
    
         
            +
                # In case of running test the applicable variation key is present
         
     | 
| 
      
 28 
     | 
    
         
            +
                # In case of fallback / paused test we pick the primary variation
         
     | 
| 
      
 29 
     | 
    
         
            +
                def applicable_variation
         
     | 
| 
      
 30 
     | 
    
         
            +
                  ActiveSupport::Notifications.instrument "oss.variation", variation: @another_key do
         
     | 
| 
      
 31 
     | 
    
         
            +
                    if @variations.any?(&variation_selector)
         
     | 
| 
      
 32 
     | 
    
         
            +
                      @variations.find(&variation_selector).call
         
     | 
| 
      
 33 
     | 
    
         
            +
                    else
         
     | 
| 
      
 34 
     | 
    
         
            +
                      primary_variation.call if primary_variation
         
     | 
| 
      
 35 
     | 
    
         
            +
                    end
         
     | 
| 
      
 36 
     | 
    
         
            +
                  end
         
     | 
| 
       20 
37 
     | 
    
         
             
                end
         
     | 
| 
       21 
38 
     | 
    
         | 
| 
       22 
     | 
    
         
            -
                 
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
      
 39 
     | 
    
         
            +
                # Primary variation is where primary: true
         
     | 
| 
      
 40 
     | 
    
         
            +
                def primary_variation
         
     | 
| 
      
 41 
     | 
    
         
            +
                  @primary_variation ||= @variations.find(&:primary)
         
     | 
| 
       24 
42 
     | 
    
         
             
                end
         
     | 
| 
       25 
43 
     | 
    
         | 
| 
       26 
     | 
    
         
            -
                 
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
      
 44 
     | 
    
         
            +
                private
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                # Scope to query on selected variation
         
     | 
| 
      
 47 
     | 
    
         
            +
                def variation_selector
         
     | 
| 
      
 48 
     | 
    
         
            +
                  ->(variation) { variation.key == @selected_variation_key }
         
     | 
| 
       28 
49 
     | 
    
         
             
                end
         
     | 
| 
       29 
50 
     | 
    
         | 
| 
       30 
     | 
    
         
            -
                 
     | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
       33 
     | 
    
         
            -
             
     | 
| 
       34 
     | 
    
         
            -
                     
     | 
| 
      
 51 
     | 
    
         
            +
                # Add all the variation to the variations collection
         
     | 
| 
      
 52 
     | 
    
         
            +
                def add_variation(key, opts = {}, &blk)
         
     | 
| 
      
 53 
     | 
    
         
            +
                  Variation.new(
         
     | 
| 
      
 54 
     | 
    
         
            +
                    key: key,
         
     | 
| 
      
 55 
     | 
    
         
            +
                    primary: opts[:primary] || false,
         
     | 
| 
      
 56 
     | 
    
         
            +
                    content: blk
         
     | 
| 
      
 57 
     | 
    
         
            +
                  ).tap do |variation_instance|
         
     | 
| 
      
 58 
     | 
    
         
            +
                    @variations << variation_instance
         
     | 
| 
       35 
59 
     | 
    
         
             
                  end
         
     | 
| 
       36 
60 
     | 
    
         
             
                end
         
     | 
| 
       37 
61 
     | 
    
         | 
| 
         @@ -14,12 +14,11 @@ module OptimizelyServerSide 
     | 
|
| 
       14 
14 
     | 
    
         
             
                #     # Code related to variation two
         
     | 
| 
       15 
15 
     | 
    
         
             
                #   end
         
     | 
| 
       16 
16 
     | 
    
         
             
                #
         
     | 
| 
       17 
     | 
    
         
            -
                #   config.variation_default('variation_default_key') do
         
     | 
| 
      
 17 
     | 
    
         
            +
                #   config.variation_default('variation_default_key', primary: true) do
         
     | 
| 
       18 
18 
     | 
    
         
             
                #     # We still want to keep our default experience
         
     | 
| 
       19 
19 
     | 
    
         
             
                #   end
         
     | 
| 
       20 
20 
     | 
    
         
             
                #
         
     | 
| 
       21 
21 
     | 
    
         
             
                # end
         
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
22 
     | 
    
         
             
                def experiment(experiment_key, &blk)
         
     | 
| 
       24 
23 
     | 
    
         
             
                  variation_key = optimizely_sdk_project_instance(experiment_key)
         
     | 
| 
       25 
24 
     | 
    
         
             
                  OptimizelyServerSide::Experiment.new(variation_key).start(&blk)
         
     | 
| 
         @@ -0,0 +1,23 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module OptimizelyServerSide
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Variation
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
                # Class holding meta data about variation.
         
     | 
| 
      
 5 
     | 
    
         
            +
                # content: The block / content of the variation
         
     | 
| 
      
 6 
     | 
    
         
            +
                # Primary: If this is the primary variation. Primary is
         
     | 
| 
      
 7 
     | 
    
         
            +
                # applicable in the cases of fallback / test is paused.
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                attr_reader :primary, :key
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                def initialize(primary: false, content: nil, key: nil)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  @primary = primary
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @key     = key
         
     | 
| 
      
 14 
     | 
    
         
            +
                  @content = content
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                # Content is a block. Call is calling that block.
         
     | 
| 
      
 18 
     | 
    
         
            +
                def call
         
     | 
| 
      
 19 
     | 
    
         
            +
                  @content.call
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
              end
         
     | 
| 
      
 23 
     | 
    
         
            +
            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. 
     | 
| 
      
 5 
     | 
    
         
            +
              s.version     = '0.0.6'
         
     | 
| 
       6 
6 
     | 
    
         
             
              s.date        = '2016-08-14'
         
     | 
| 
       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  
     | 
| 
      
 8 
     | 
    
         
            +
              s.description = "Optimizely server side. A A/B 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")
         
     | 
| 
         @@ -16,6 +16,7 @@ Gem::Specification.new do |s| 
     | 
|
| 
       16 
16 
     | 
    
         
             
                'https://github.com/ankit8898/optimizely_server_side'
         
     | 
| 
       17 
17 
     | 
    
         
             
              s.license       = 'MIT'
         
     | 
| 
       18 
18 
     | 
    
         
             
              s.add_development_dependency 'rspec', '~> 3.5'
         
     | 
| 
      
 19 
     | 
    
         
            +
              s.add_development_dependency 'rspec-collection_matchers', '~> 1.1', '>= 1.1.2'
         
     | 
| 
       19 
20 
     | 
    
         
             
              s.add_development_dependency 'webmock', '~> 2.1'
         
     | 
| 
       20 
21 
     | 
    
         
             
              s.add_runtime_dependency 'optimizely-sdk' , '~> 0.1.1'
         
     | 
| 
       21 
22 
     | 
    
         
             
              s.add_runtime_dependency 'activesupport', '~> 4.2', '>= 4.2.6'
         
     | 
| 
         @@ -5,7 +5,7 @@ RSpec.describe OptimizelyServerSide::Experiment do 
     | 
|
| 
       5 
5 
     | 
    
         
             
              subject { OptimizelyServerSide::Experiment.new(variation_key = 'variation_key_a') }
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
       7 
7 
     | 
    
         | 
| 
       8 
     | 
    
         
            -
              describe '# 
     | 
| 
      
 8 
     | 
    
         
            +
              describe '#applicable_variation' do
         
     | 
| 
       9 
9 
     | 
    
         | 
| 
       10 
10 
     | 
    
         
             
                before do
         
     | 
| 
       11 
11 
     | 
    
         | 
| 
         @@ -22,7 +22,7 @@ RSpec.describe OptimizelyServerSide::Experiment do 
     | 
|
| 
       22 
22 
     | 
    
         
             
                context 'when variation_key is present' do
         
     | 
| 
       23 
23 
     | 
    
         | 
| 
       24 
24 
     | 
    
         
             
                  it 'should result variation b' do
         
     | 
| 
       25 
     | 
    
         
            -
                    expect(subject. 
     | 
| 
      
 25 
     | 
    
         
            +
                    expect(subject.applicable_variation).to eq('experience a')
         
     | 
| 
       26 
26 
     | 
    
         
             
                  end
         
     | 
| 
       27 
27 
     | 
    
         | 
| 
       28 
28 
     | 
    
         
             
                end
         
     | 
| 
         @@ -32,7 +32,7 @@ RSpec.describe OptimizelyServerSide::Experiment do 
     | 
|
| 
       32 
32 
     | 
    
         
             
                  subject { OptimizelyServerSide::Experiment.new(variation_key = '') }
         
     | 
| 
       33 
33 
     | 
    
         | 
| 
       34 
34 
     | 
    
         
             
                  it 'should be nil' do
         
     | 
| 
       35 
     | 
    
         
            -
                    expect(subject. 
     | 
| 
      
 35 
     | 
    
         
            +
                    expect(subject.applicable_variation).to be_nil
         
     | 
| 
       36 
36 
     | 
    
         
             
                  end
         
     | 
| 
       37 
37 
     | 
    
         
             
                end
         
     | 
| 
       38 
38 
     | 
    
         | 
| 
         @@ -43,9 +43,26 @@ RSpec.describe OptimizelyServerSide::Experiment do 
     | 
|
| 
       43 
43 
     | 
    
         | 
| 
       44 
44 
     | 
    
         
             
                let(:blk) { Proc.new { 'Hello!'} }
         
     | 
| 
       45 
45 
     | 
    
         | 
| 
       46 
     | 
    
         
            -
                 
     | 
| 
       47 
     | 
    
         
            -
                   
     | 
| 
      
 46 
     | 
    
         
            +
                before do
         
     | 
| 
      
 47 
     | 
    
         
            +
                  @variation_instance = subject.variation_one('foo', &blk)
         
     | 
| 
      
 48 
     | 
    
         
            +
                end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                it 'returns a variation instance passed' do
         
     | 
| 
      
 51 
     | 
    
         
            +
                  expect(@variation_instance).to be_kind_of(OptimizelyServerSide::Variation)
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                it 'returns a key of foo' do
         
     | 
| 
      
 55 
     | 
    
         
            +
                  expect(@variation_instance.key).to eq('foo')
         
     | 
| 
      
 56 
     | 
    
         
            +
                end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                it 'returns a content with blk ' do
         
     | 
| 
      
 59 
     | 
    
         
            +
                  expect(@variation_instance.instance_variable_get(:@content)).to eq(blk)
         
     | 
| 
      
 60 
     | 
    
         
            +
                end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                it 'is not primary' do
         
     | 
| 
      
 63 
     | 
    
         
            +
                  expect(@variation_instance.primary).to be(false)
         
     | 
| 
       48 
64 
     | 
    
         
             
                end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
       49 
66 
     | 
    
         
             
              end
         
     | 
| 
       50 
67 
     | 
    
         | 
| 
       51 
68 
     | 
    
         | 
| 
         @@ -53,8 +70,24 @@ RSpec.describe OptimizelyServerSide::Experiment do 
     | 
|
| 
       53 
70 
     | 
    
         | 
| 
       54 
71 
     | 
    
         
             
                let(:blk) { -> {OpenStruct.new } }
         
     | 
| 
       55 
72 
     | 
    
         | 
| 
       56 
     | 
    
         
            -
                 
     | 
| 
       57 
     | 
    
         
            -
                   
     | 
| 
      
 73 
     | 
    
         
            +
                before do
         
     | 
| 
      
 74 
     | 
    
         
            +
                  @variation_instance = subject.variation_two('foo', &blk)
         
     | 
| 
      
 75 
     | 
    
         
            +
                end
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                it 'returns a variation instance passed' do
         
     | 
| 
      
 78 
     | 
    
         
            +
                  expect(@variation_instance).to be_kind_of(OptimizelyServerSide::Variation)
         
     | 
| 
      
 79 
     | 
    
         
            +
                end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                it 'returns a key of foo' do
         
     | 
| 
      
 82 
     | 
    
         
            +
                  expect(@variation_instance.key).to eq('foo')
         
     | 
| 
      
 83 
     | 
    
         
            +
                end
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                it 'returns a content with blk ' do
         
     | 
| 
      
 86 
     | 
    
         
            +
                  expect(@variation_instance.instance_variable_get(:@content)).to eq(blk)
         
     | 
| 
      
 87 
     | 
    
         
            +
                end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                it 'is not primary' do
         
     | 
| 
      
 90 
     | 
    
         
            +
                  expect(@variation_instance.primary).to be(false)
         
     | 
| 
       58 
91 
     | 
    
         
             
                end
         
     | 
| 
       59 
92 
     | 
    
         
             
              end
         
     | 
| 
       60 
93 
     | 
    
         | 
| 
         @@ -62,12 +95,53 @@ RSpec.describe OptimizelyServerSide::Experiment do 
     | 
|
| 
       62 
95 
     | 
    
         | 
| 
       63 
96 
     | 
    
         
             
                let(:blk) { Proc.new { 'Hello!'} }
         
     | 
| 
       64 
97 
     | 
    
         | 
| 
       65 
     | 
    
         
            -
                 
     | 
| 
       66 
     | 
    
         
            -
                   
     | 
| 
      
 98 
     | 
    
         
            +
                before do
         
     | 
| 
      
 99 
     | 
    
         
            +
                  @variation_instance = subject.variation_three('foo', &blk)
         
     | 
| 
      
 100 
     | 
    
         
            +
                end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                it 'returns a variation instance passed' do
         
     | 
| 
      
 103 
     | 
    
         
            +
                  expect(@variation_instance).to be_kind_of(OptimizelyServerSide::Variation)
         
     | 
| 
      
 104 
     | 
    
         
            +
                end
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
                it 'returns a key of foo' do
         
     | 
| 
      
 107 
     | 
    
         
            +
                  expect(@variation_instance.key).to eq('foo')
         
     | 
| 
      
 108 
     | 
    
         
            +
                end
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
                it 'returns a content with blk ' do
         
     | 
| 
      
 111 
     | 
    
         
            +
                  expect(@variation_instance.instance_variable_get(:@content)).to eq(blk)
         
     | 
| 
      
 112 
     | 
    
         
            +
                end
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
                it 'is not primary' do
         
     | 
| 
      
 115 
     | 
    
         
            +
                  expect(@variation_instance.primary).to be(false)
         
     | 
| 
       67 
116 
     | 
    
         
             
                end
         
     | 
| 
       68 
117 
     | 
    
         
             
              end
         
     | 
| 
       69 
118 
     | 
    
         | 
| 
       70 
     | 
    
         
            -
              describe '# 
     | 
| 
      
 119 
     | 
    
         
            +
              describe '#variation_default' do
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
                let(:blk) { -> {'<div><h1>Hello</h1></div>'} }
         
     | 
| 
      
 122 
     | 
    
         
            +
             
     | 
| 
      
 123 
     | 
    
         
            +
                before do
         
     | 
| 
      
 124 
     | 
    
         
            +
                  @variation_instance = subject.variation_default('foo', primary: true, &blk)
         
     | 
| 
      
 125 
     | 
    
         
            +
                end
         
     | 
| 
      
 126 
     | 
    
         
            +
             
     | 
| 
      
 127 
     | 
    
         
            +
                it 'returns a variation instance passed' do
         
     | 
| 
      
 128 
     | 
    
         
            +
                  expect(@variation_instance).to be_kind_of(OptimizelyServerSide::Variation)
         
     | 
| 
      
 129 
     | 
    
         
            +
                end
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
                it 'returns a key of foo' do
         
     | 
| 
      
 132 
     | 
    
         
            +
                  expect(@variation_instance.key).to eq('foo')
         
     | 
| 
      
 133 
     | 
    
         
            +
                end
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
                it 'returns a content with blk ' do
         
     | 
| 
      
 136 
     | 
    
         
            +
                  expect(@variation_instance.instance_variable_get(:@content)).to eq(blk)
         
     | 
| 
      
 137 
     | 
    
         
            +
                end
         
     | 
| 
      
 138 
     | 
    
         
            +
             
     | 
| 
      
 139 
     | 
    
         
            +
                it 'is primary' do
         
     | 
| 
      
 140 
     | 
    
         
            +
                  expect(@variation_instance.primary).to be(true)
         
     | 
| 
      
 141 
     | 
    
         
            +
                end
         
     | 
| 
      
 142 
     | 
    
         
            +
              end
         
     | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
      
 144 
     | 
    
         
            +
              describe '#variations' do
         
     | 
| 
       71 
145 
     | 
    
         | 
| 
       72 
146 
     | 
    
         
             
                context 'key accepts regular strings' do
         
     | 
| 
       73 
147 
     | 
    
         | 
| 
         @@ -77,8 +151,16 @@ RSpec.describe OptimizelyServerSide::Experiment do 
     | 
|
| 
       77 
151 
     | 
    
         
             
                    subject.variation_one('foo', &string_lambda)
         
     | 
| 
       78 
152 
     | 
    
         
             
                  end
         
     | 
| 
       79 
153 
     | 
    
         | 
| 
       80 
     | 
    
         
            -
                  it ' 
     | 
| 
       81 
     | 
    
         
            -
                    expect(subject.instance_variable_get(:@ 
     | 
| 
      
 154 
     | 
    
         
            +
                  it 'holds collection of variations' do
         
     | 
| 
      
 155 
     | 
    
         
            +
                    expect(subject.instance_variable_get(:@variations)).to have(1).items
         
     | 
| 
      
 156 
     | 
    
         
            +
                  end
         
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
      
 158 
     | 
    
         
            +
                  it 'is a type of Variation' do
         
     | 
| 
      
 159 
     | 
    
         
            +
                    expect(subject.instance_variable_get(:@variations)[0]).to be_kind_of(OptimizelyServerSide::Variation)
         
     | 
| 
      
 160 
     | 
    
         
            +
                  end
         
     | 
| 
      
 161 
     | 
    
         
            +
             
     | 
| 
      
 162 
     | 
    
         
            +
                  it 'is having the block content' do
         
     | 
| 
      
 163 
     | 
    
         
            +
                    expect(subject.instance_variable_get(:@variations)[0].call).to eq('I am a variation')
         
     | 
| 
       82 
164 
     | 
    
         
             
                  end
         
     | 
| 
       83 
165 
     | 
    
         | 
| 
       84 
166 
     | 
    
         
             
                end
         
     | 
| 
         @@ -92,8 +174,12 @@ RSpec.describe OptimizelyServerSide::Experiment do 
     | 
|
| 
       92 
174 
     | 
    
         
             
                    subject.variation_one('foo', &some_method)
         
     | 
| 
       93 
175 
     | 
    
         
             
                  end
         
     | 
| 
       94 
176 
     | 
    
         | 
| 
       95 
     | 
    
         
            -
                  it 'has  
     | 
| 
       96 
     | 
    
         
            -
                    expect(subject.instance_variable_get(:@ 
     | 
| 
      
 177 
     | 
    
         
            +
                  it 'has content as proc' do
         
     | 
| 
      
 178 
     | 
    
         
            +
                    expect(subject.instance_variable_get(:@variations)[0].instance_variable_get(:@content)).to eq(some_method)
         
     | 
| 
      
 179 
     | 
    
         
            +
                  end
         
     | 
| 
      
 180 
     | 
    
         
            +
             
     | 
| 
      
 181 
     | 
    
         
            +
                  it 'has key' do
         
     | 
| 
      
 182 
     | 
    
         
            +
                    expect(subject.instance_variable_get(:@variations)[0].key).to eq('foo')
         
     | 
| 
       97 
183 
     | 
    
         
             
                  end
         
     | 
| 
       98 
184 
     | 
    
         | 
| 
       99 
185 
     | 
    
         
             
                end
         
     | 
| 
         @@ -129,10 +215,72 @@ RSpec.describe OptimizelyServerSide::Experiment do 
     | 
|
| 
       129 
215 
     | 
    
         
             
                    subject.variation_three('foo_three', &string_blk)
         
     | 
| 
       130 
216 
     | 
    
         
             
                  end
         
     | 
| 
       131 
217 
     | 
    
         | 
| 
       132 
     | 
    
         
            -
                  it 'has  
     | 
| 
       133 
     | 
    
         
            -
                    expect(subject.instance_variable_get(:@ 
     | 
| 
      
 218 
     | 
    
         
            +
                  it 'has all variations' do
         
     | 
| 
      
 219 
     | 
    
         
            +
                    expect(subject.instance_variable_get(:@variations)).to have(3).items
         
     | 
| 
      
 220 
     | 
    
         
            +
                  end
         
     | 
| 
      
 221 
     | 
    
         
            +
             
     | 
| 
      
 222 
     | 
    
         
            +
                  it 'has all variations of class Variation' do
         
     | 
| 
      
 223 
     | 
    
         
            +
                    expect(subject.instance_variable_get(:@variations)).to all(be_an(OptimizelyServerSide::Variation))
         
     | 
| 
      
 224 
     | 
    
         
            +
                  end
         
     | 
| 
      
 225 
     | 
    
         
            +
             
     | 
| 
      
 226 
     | 
    
         
            +
                end
         
     | 
| 
      
 227 
     | 
    
         
            +
              end
         
     | 
| 
      
 228 
     | 
    
         
            +
             
     | 
| 
      
 229 
     | 
    
         
            +
             
     | 
| 
      
 230 
     | 
    
         
            +
              describe '#primary_variation' do
         
     | 
| 
      
 231 
     | 
    
         
            +
             
     | 
| 
      
 232 
     | 
    
         
            +
                let(:some_method) { Proc.new {|n| n*2 } }
         
     | 
| 
      
 233 
     | 
    
         
            +
             
     | 
| 
      
 234 
     | 
    
         
            +
                let(:some_html_block) do
         
     | 
| 
      
 235 
     | 
    
         
            +
                  -> { '<h1>Foo</h1>' }
         
     | 
| 
      
 236 
     | 
    
         
            +
                end
         
     | 
| 
      
 237 
     | 
    
         
            +
             
     | 
| 
      
 238 
     | 
    
         
            +
                let(:string_blk) { -> { 'Hello!'} }
         
     | 
| 
      
 239 
     | 
    
         
            +
             
     | 
| 
      
 240 
     | 
    
         
            +
             
     | 
| 
      
 241 
     | 
    
         
            +
                context 'when nothing is marked as primary' do
         
     | 
| 
      
 242 
     | 
    
         
            +
             
     | 
| 
      
 243 
     | 
    
         
            +
                  before do
         
     | 
| 
      
 244 
     | 
    
         
            +
                    subject.variation_one('foo', &some_method)
         
     | 
| 
      
 245 
     | 
    
         
            +
             
     | 
| 
      
 246 
     | 
    
         
            +
                    subject.variation_two('foo_two', &some_html_block)
         
     | 
| 
      
 247 
     | 
    
         
            +
             
     | 
| 
      
 248 
     | 
    
         
            +
                    subject.variation_three('foo_three', &string_blk)
         
     | 
| 
      
 249 
     | 
    
         
            +
                  end
         
     | 
| 
      
 250 
     | 
    
         
            +
             
     | 
| 
      
 251 
     | 
    
         
            +
                  it { expect(subject.primary_variation).to be_nil }
         
     | 
| 
      
 252 
     | 
    
         
            +
                end
         
     | 
| 
      
 253 
     | 
    
         
            +
             
     | 
| 
      
 254 
     | 
    
         
            +
                context 'when one is marked as primary' do
         
     | 
| 
      
 255 
     | 
    
         
            +
             
     | 
| 
      
 256 
     | 
    
         
            +
                  before do
         
     | 
| 
      
 257 
     | 
    
         
            +
                    subject.variation_one('foo', &some_method)
         
     | 
| 
      
 258 
     | 
    
         
            +
             
     | 
| 
      
 259 
     | 
    
         
            +
                    subject.variation_two('foo_two',primary: true, &some_html_block)
         
     | 
| 
      
 260 
     | 
    
         
            +
             
     | 
| 
      
 261 
     | 
    
         
            +
                    subject.variation_three('foo_three', &string_blk)
         
     | 
| 
       134 
262 
     | 
    
         
             
                  end
         
     | 
| 
       135 
263 
     | 
    
         | 
| 
      
 264 
     | 
    
         
            +
                  it { expect(subject.primary_variation).not_to be_nil }
         
     | 
| 
      
 265 
     | 
    
         
            +
             
     | 
| 
      
 266 
     | 
    
         
            +
                  it { expect(subject.primary_variation.call).to eq('<h1>Foo</h1>') }
         
     | 
| 
       136 
267 
     | 
    
         
             
                end
         
     | 
| 
      
 268 
     | 
    
         
            +
             
     | 
| 
      
 269 
     | 
    
         
            +
             
     | 
| 
      
 270 
     | 
    
         
            +
                context 'when multiple are marked as primary' do
         
     | 
| 
      
 271 
     | 
    
         
            +
             
     | 
| 
      
 272 
     | 
    
         
            +
                  before do
         
     | 
| 
      
 273 
     | 
    
         
            +
                    subject.variation_one('foo', &some_method)
         
     | 
| 
      
 274 
     | 
    
         
            +
             
     | 
| 
      
 275 
     | 
    
         
            +
                    subject.variation_three('foo_two', primary: true, &some_html_block)
         
     | 
| 
      
 276 
     | 
    
         
            +
             
     | 
| 
      
 277 
     | 
    
         
            +
                    subject.variation_two('foo_three',primary: true, &string_blk)
         
     | 
| 
      
 278 
     | 
    
         
            +
                  end
         
     | 
| 
      
 279 
     | 
    
         
            +
             
     | 
| 
      
 280 
     | 
    
         
            +
                  it { expect(subject.primary_variation).not_to be_nil }
         
     | 
| 
      
 281 
     | 
    
         
            +
             
     | 
| 
      
 282 
     | 
    
         
            +
                  it { expect(subject.primary_variation.call).to eq('<h1>Foo</h1>') }
         
     | 
| 
      
 283 
     | 
    
         
            +
                end
         
     | 
| 
      
 284 
     | 
    
         
            +
             
     | 
| 
       137 
285 
     | 
    
         
             
              end
         
     | 
| 
       138 
286 
     | 
    
         
             
            end
         
     | 
| 
         @@ -0,0 +1,75 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            RSpec.describe OptimizelyServerSide::Variation do
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
              describe '#primary' do
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                context 'when no primary is passed' do
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  subject { described_class.new }
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  it 'defaults to false' do
         
     | 
| 
      
 12 
     | 
    
         
            +
                    expect(subject.primary).to be(false)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                context 'when primary is passed' do
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  subject { described_class.new(primary: true) }
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  it 'is as per passed' do
         
     | 
| 
      
 22 
     | 
    
         
            +
                    expect(subject.primary).to be(true)
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
              end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
              describe '#content' do
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                context 'when no content is passed' do
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  subject { described_class.new }
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                  it 'defaults to nil' do
         
     | 
| 
      
 36 
     | 
    
         
            +
                    expect(subject.instance_variable_get(:@content)).to be_nil
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                context 'when content is passed' do
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                  let(:some_proc) { Proc.new { |n| "Hello #{n} world!"} }
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                  subject { described_class.new(content: some_proc) }
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                  it 'is as per passed' do
         
     | 
| 
      
 48 
     | 
    
         
            +
                    expect(subject.instance_variable_get(:@content)).to be(some_proc)
         
     | 
| 
      
 49 
     | 
    
         
            +
                  end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                end
         
     | 
| 
      
 52 
     | 
    
         
            +
              end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
              describe '#key' do
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                context 'when no key is passed' do
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                  subject { described_class.new }
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                  it 'defaults to nil' do
         
     | 
| 
      
 61 
     | 
    
         
            +
                    expect(subject.instance_variable_get(:@key)).to be_nil
         
     | 
| 
      
 62 
     | 
    
         
            +
                  end
         
     | 
| 
      
 63 
     | 
    
         
            +
                end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                context 'when key is passed' do
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                  subject { described_class.new(key: 'ankit_test') }
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                  it 'is as per passed' do
         
     | 
| 
      
 71 
     | 
    
         
            +
                    expect(subject.instance_variable_get(:@key)).to eq('ankit_test')
         
     | 
| 
      
 72 
     | 
    
         
            +
                  end
         
     | 
| 
      
 73 
     | 
    
         
            +
                end
         
     | 
| 
      
 74 
     | 
    
         
            +
              end
         
     | 
| 
      
 75 
     | 
    
         
            +
            end
         
     | 
    
        data/spec/spec_helper.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: optimizely_server_side
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0.0. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.0.6
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Ankit Gupta
         
     | 
| 
         @@ -24,6 +24,26 @@ dependencies: 
     | 
|
| 
       24 
24 
     | 
    
         
             
                - - "~>"
         
     | 
| 
       25 
25 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       26 
26 
     | 
    
         
             
                    version: '3.5'
         
     | 
| 
      
 27 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 28 
     | 
    
         
            +
              name: rspec-collection_matchers
         
     | 
| 
      
 29 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 30 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 31 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 32 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 33 
     | 
    
         
            +
                    version: '1.1'
         
     | 
| 
      
 34 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 35 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 36 
     | 
    
         
            +
                    version: 1.1.2
         
     | 
| 
      
 37 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 38 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 39 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 40 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 41 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 42 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 43 
     | 
    
         
            +
                    version: '1.1'
         
     | 
| 
      
 44 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 45 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 46 
     | 
    
         
            +
                    version: 1.1.2
         
     | 
| 
       27 
47 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       28 
48 
     | 
    
         
             
              name: webmock
         
     | 
| 
       29 
49 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
         @@ -72,9 +92,9 @@ dependencies: 
     | 
|
| 
       72 
92 
     | 
    
         
             
                - - ">="
         
     | 
| 
       73 
93 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       74 
94 
     | 
    
         
             
                    version: 4.2.6
         
     | 
| 
       75 
     | 
    
         
            -
            description: 'Optimizely server side. A  
     | 
| 
       76 
     | 
    
         
            -
              sdk for easy caching of server side config and exposing few more utility helpers. 
     | 
| 
       77 
     | 
    
         
            -
              of fallbacks and marking primary experiments. '
         
     | 
| 
      
 95 
     | 
    
         
            +
            description: 'Optimizely server side. A A/B test wrapper on top of optimizely''s ruby
         
     | 
| 
      
 96 
     | 
    
         
            +
              sdk for easy caching of server side config and exposing few more utility helpers.
         
     | 
| 
      
 97 
     | 
    
         
            +
              Handling of fallbacks and marking primary experiments. '
         
     | 
| 
       78 
98 
     | 
    
         
             
            email: ankit.gupta8898@gmail.com
         
     | 
| 
       79 
99 
     | 
    
         
             
            executables: []
         
     | 
| 
       80 
100 
     | 
    
         
             
            extensions: []
         
     | 
| 
         @@ -96,6 +116,7 @@ files: 
     | 
|
| 
       96 
116 
     | 
    
         
             
            - lib/optimizely_server_side/experiment.rb
         
     | 
| 
       97 
117 
     | 
    
         
             
            - lib/optimizely_server_side/helpers/support.rb
         
     | 
| 
       98 
118 
     | 
    
         
             
            - lib/optimizely_server_side/optimizely_sdk.rb
         
     | 
| 
      
 119 
     | 
    
         
            +
            - lib/optimizely_server_side/variation.rb
         
     | 
| 
       99 
120 
     | 
    
         
             
            - optimizely_server_side.gemspec
         
     | 
| 
       100 
121 
     | 
    
         
             
            - spec/optimizely_server_side/cache_spec.rb
         
     | 
| 
       101 
122 
     | 
    
         
             
            - spec/optimizely_server_side/configuration_spec.rb
         
     | 
| 
         @@ -103,6 +124,7 @@ files: 
     | 
|
| 
       103 
124 
     | 
    
         
             
            - spec/optimizely_server_side/experiment_spec.rb
         
     | 
| 
       104 
125 
     | 
    
         
             
            - spec/optimizely_server_side/helpers/support_spec.rb
         
     | 
| 
       105 
126 
     | 
    
         
             
            - spec/optimizely_server_side/optimizely_sdk_spec.rb
         
     | 
| 
      
 127 
     | 
    
         
            +
            - spec/optimizely_server_side/variation_spec.rb
         
     | 
| 
       106 
128 
     | 
    
         
             
            - spec/optimizely_server_side_spec.rb
         
     | 
| 
       107 
129 
     | 
    
         
             
            - spec/spec_helper.rb
         
     | 
| 
       108 
130 
     | 
    
         
             
            homepage: https://github.com/ankit8898/optimizely_server_side
         
     | 
| 
         @@ -137,5 +159,6 @@ test_files: 
     | 
|
| 
       137 
159 
     | 
    
         
             
            - spec/optimizely_server_side/experiment_spec.rb
         
     | 
| 
       138 
160 
     | 
    
         
             
            - spec/optimizely_server_side/helpers/support_spec.rb
         
     | 
| 
       139 
161 
     | 
    
         
             
            - spec/optimizely_server_side/optimizely_sdk_spec.rb
         
     | 
| 
      
 162 
     | 
    
         
            +
            - spec/optimizely_server_side/variation_spec.rb
         
     | 
| 
       140 
163 
     | 
    
         
             
            - spec/optimizely_server_side_spec.rb
         
     | 
| 
       141 
164 
     | 
    
         
             
            - spec/spec_helper.rb
         
     |