ab_panel 0.3.3 → 0.4.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: fe1dec59d88584288c8ada336cae1788b0fd0543
4
- data.tar.gz: d212f5ecd9685c359720bf935750582fe6036be9
2
+ SHA256:
3
+ metadata.gz: 37ee0a4c2ef876a4211289f684ba7db3d620d34bfdd2a54081bbc92c0b94240b
4
+ data.tar.gz: 47f71b412b1021c6b3f7034e209f4c80a490950b1ce1b92e68070b1d12ae84d8
5
5
  SHA512:
6
- metadata.gz: 980f2a2130011fce8dd78002f15546d701ddf15de16477588aeba852b140431e4931854d63ac660443757358d8b4fb38c74a094beb715583debf1bebde515fc3
7
- data.tar.gz: 582ef9a3270130ad244b76137225cf0df80b88154f00a2e20a4cee68706a924ada234619ddb8928ba8a20f946ccf505d32a1eab15890530ed9128cda6a37a854
6
+ metadata.gz: becb21058455ab271a01771df8643c0002141d0f8836ae77503f516aaaeee2f187cc7d6965c6207cee572ef54413a186e230c6bc64fb72f1f89f0c7a0051fde6
7
+ data.tar.gz: cbb3437fd90843d080251acf50302be43abd2f12403129442f5d1c439789bdcf8061cd9861327b1b9c5b3df1dc0d91120fd0f9e885c4723a8b24877444d5cd31
data/.travis.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  language: ruby
2
2
  script: 'bundle exec rspec spec'
3
3
  rvm:
4
- - 2.1.5
4
+ - 2.1.7
data/ab_panel.gemspec CHANGED
@@ -6,10 +6,9 @@ require 'ab_panel/version'
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "ab_panel"
8
8
  spec.version = AbPanel::VERSION
9
- spec.authors = ["Wouter de Vos", "Mark Mulder", "Peter de Ruijter"]
10
- spec.email = ["wouter@springest.com", "markmulder@gmail.com", "hello@thisiswho.im"]
11
- spec.description = %q{Run A/B test experiments on your Rails 3+ site using Mixpanel as a backend.}
12
- spec.summary = %q{Run A/B test experiments on your Rails 3+ site using Mixpanel as a backend.}
9
+ spec.authors = ["Dennis Paagman", "Eugene Pimenov", "Jordy van Gelder", "Mark Mulder", "Peter de Ruijter", "Tim Flapper", "Wouter de Vos"]
10
+ spec.description = %q{Run A/B test experiments on your Rails 4+ site using Mixpanel as a backend.}
11
+ spec.summary = %q{Run A/B test experiments on your Rails 4+ site using Mixpanel as a backend.}
13
12
  spec.homepage = "https://github.com/Springest/ab_panel"
14
13
  spec.license = "MIT"
15
14
 
@@ -19,11 +18,11 @@ Gem::Specification.new do |spec|
19
18
  spec.require_paths = ["lib"]
20
19
 
21
20
  spec.add_development_dependency "bundler", "~> 1.3"
22
- spec.add_development_dependency "rails", '~> 3.2'
23
21
  spec.add_development_dependency "rake"
24
22
  spec.add_development_dependency "fakeweb"
25
23
  spec.add_development_dependency "rspec"
26
24
  spec.add_development_dependency "byebug"
27
25
 
26
+ spec.add_runtime_dependency "rails", '>= 4.0'
28
27
  spec.add_runtime_dependency "mixpanel"
29
28
  end
data/lib/ab_panel.rb CHANGED
@@ -22,6 +22,16 @@ module AbPanel
22
22
  Thread.current[:ab_panel_conditions] ||= assign_conditions!
23
23
  end
24
24
 
25
+ def serialized_conditions
26
+ cs = {}
27
+
28
+ conditions.each_pair do |key, value|
29
+ cs[key] = value.marshal_dump
30
+ end
31
+
32
+ cs.to_json
33
+ end
34
+
25
35
  # Set the experiment's conditions.
26
36
  #
27
37
  # This is used to persist conditions from
@@ -74,11 +84,30 @@ module AbPanel
74
84
  funnels.add(funnel) if funnel.present?
75
85
  end
76
86
 
87
+ def environment
88
+ props = { distinct_id: self.env["distinct_id"] }
89
+ props.merge!(self.properties) if self.properties
90
+
91
+ self.funnels.each { |f| props["funnel_#{f}"] = true }
92
+
93
+ self.experiments.each { |exp| props[exp] = self.conditions.send(exp).condition }
94
+
95
+ props
96
+ end
97
+
77
98
  private # ----------------------------------------------------------------------------
78
99
 
79
100
  def assign_conditions!(already_assigned=nil)
80
101
  cs = {}
81
102
 
103
+ if already_assigned
104
+ already_assigned.each do |key, value|
105
+ already_assigned[key] = OpenStruct.new(already_assigned[key])
106
+ end
107
+ end
108
+
109
+ already_assigned = OpenStruct.new already_assigned
110
+
82
111
  experiments.each do |experiment|
83
112
  cs[experiment] ||= {}
84
113
 
@@ -27,8 +27,20 @@ module AbPanel
27
27
  #
28
28
  # `current_user.id` for logged in users.
29
29
  def distinct_id
30
- cookies.signed['distinct_id'] ||=
31
- (0..4).map { |i| i.even? ? ('A'..'Z').to_a[rand(26)] : rand(10) }.join
30
+ distinct_id = cookies.signed['distinct_id']
31
+
32
+ return distinct_id if distinct_id
33
+
34
+ distinct_id = (0..4).map { |i| i.even? ? ('A'..'Z').to_a[rand(26)] : rand(10) }.join
35
+
36
+ cookies.signed['distinct_id'] =
37
+ {
38
+ value: distinct_id,
39
+ httponly: true,
40
+ secure: request.ssl?
41
+ }
42
+
43
+ distinct_id
32
44
  end
33
45
 
34
46
  def ab_panel_options
@@ -48,10 +60,27 @@ module AbPanel
48
60
  # in the user's session.
49
61
  def initialize_ab_panel!(options = {})
50
62
  AbPanel.reset!
51
- AbPanel.conditions = cookies.signed['ab_panel_conditions']
52
- cookies.signed['ab_panel_conditions'] = AbPanel.conditions
53
- AbPanel.funnels = cookies.signed['ab_panel_funnels']
54
- cookies.signed['ab_panel_funnels'] = AbPanel.funnels
63
+
64
+
65
+ AbPanel.conditions =
66
+ if cookies.signed[:ab_panel_conditions]
67
+ JSON.parse(cookies.signed[:ab_panel_conditions])
68
+ else
69
+ nil
70
+ end
71
+
72
+ cookies.signed[:ab_panel_conditions] = {
73
+ value: AbPanel.serialized_conditions,
74
+ httponly: true,
75
+ secure: request.ssl?
76
+ }
77
+
78
+ AbPanel.funnels = Set.new(cookies.signed[:ab_panel_funnels])
79
+ cookies.signed[:ab_panel_funnels] = {
80
+ value: AbPanel.funnels,
81
+ httponly: true,
82
+ secure: request.ssl?
83
+ }
55
84
 
56
85
  {
57
86
  'distinct_id' => distinct_id,
@@ -80,7 +109,6 @@ module AbPanel
80
109
 
81
110
  options = {
82
111
  distinct_id: distinct_id,
83
- ip: request.remote_ip,
84
112
  time: Time.now.utc,
85
113
  }.merge(properties)
86
114
 
@@ -1,14 +1,8 @@
1
1
  module AbPanel
2
2
  class Javascript
3
3
  def self.environment
4
- props = { distinct_id: AbPanel.env["distinct_id"] }
5
- props.merge!(AbPanel.properties) if AbPanel.properties
6
-
7
- AbPanel.funnels.each { |f| props["funnel_#{f}"] = true }
8
-
9
- AbPanel.experiments.each { |exp| props[exp] = AbPanel.conditions.send(exp).condition }
10
-
11
- props.to_json
4
+ AbPanel.environment.to_json
12
5
  end
6
+
13
7
  end
14
8
  end
@@ -1,3 +1,3 @@
1
1
  module AbPanel
2
- VERSION = "0.3.3"
2
+ VERSION = "0.4.4"
3
3
  end
@@ -4,32 +4,32 @@ describe AbPanel::Config do
4
4
  let(:config) { AbPanel::Config.new }
5
5
  context "config" do
6
6
  before do
7
- AbPanel::Config.any_instance.stub(:settings) { { exp1: { scenario1: 25, scenario2: 75 } } }
7
+ allow_any_instance_of(AbPanel::Config).to receive(:settings) { { exp1: { scenario1: 25, scenario2: 75 } } }
8
8
  end
9
9
 
10
10
  describe '.experiments' do
11
11
  subject { config.experiments }
12
- it { should =~ [:exp1] }
12
+ it { is_expected.to match_array [:exp1] }
13
13
  end
14
14
 
15
15
  describe '.weights' do
16
16
  subject { config.weights('exp1') }
17
17
 
18
- it { should =~ [75.0, 25.0] }
18
+ it { is_expected.to match_array [75.0, 25.0] }
19
19
  end
20
20
  end
21
21
  context "empty config" do
22
22
  before do
23
- YAML.stub(:load) { false }
23
+ allow(YAML).to receive(:load) { false }
24
24
  end
25
25
  describe ".settings" do
26
26
  subject { config.settings }
27
- it { should eq nil }
27
+ it { is_expected.to eq nil }
28
28
  end
29
29
 
30
30
  describe ".experiments" do
31
31
  subject { config.experiments }
32
- it { should == {} }
32
+ it { is_expected.to eq({}) }
33
33
  end
34
34
  end
35
35
  end
@@ -13,9 +13,12 @@ describe AbPanel::ControllerAdditions do
13
13
 
14
14
  describe "#distinct_id" do
15
15
  let(:cookies) { {} }
16
- before { controller.stub_chain(:cookies, :signed).and_return(cookies) }
16
+ before do
17
+ allow(controller).to receive_message_chain(:request, :ssl?).and_return(true)
18
+ allow(controller).to receive_message_chain(:cookies, :signed).and_return(cookies)
19
+ end
17
20
  subject { controller.distinct_id }
18
21
 
19
- it { should match /^([A-Z]|[0-9])([A-Z]|[0-9])([A-Z]|[0-9])([A-Z]|[0-9])([A-Z]|[0-9])$/ }
22
+ it { is_expected.to match /^([A-Z]|[0-9])([A-Z]|[0-9])([A-Z]|[0-9])([A-Z]|[0-9])([A-Z]|[0-9])$/ }
20
23
  end
21
24
  end
@@ -5,12 +5,12 @@ describe AbPanel::Javascript do
5
5
  AbPanel.set_env('distinct_id', 'distinct_id')
6
6
  AbPanel.set_env(:properties, { post_name: 'test' })
7
7
  result = JSON.parse(AbPanel::Javascript.environment)
8
- result['distinct_id'].should == 'distinct_id'
8
+ expect(result['distinct_id']).to eq 'distinct_id'
9
9
  end
10
10
 
11
11
  it 'works without extra properties' do
12
12
  AbPanel.set_env(:properties, nil)
13
13
  result = JSON.parse(AbPanel::Javascript.environment)
14
- result['distinct_id'].should == 'distinct_id'
14
+ expect(result['distinct_id']).to eq 'distinct_id'
15
15
  end
16
16
  end
@@ -4,14 +4,14 @@ describe AbPanel do
4
4
  describe ".experiments" do
5
5
  subject { AbPanel.experiments }
6
6
 
7
- it { should =~ %w(experiment1 experiment2).map(&:to_sym) }
7
+ it { is_expected.to match_array %w(experiment1 experiment2).map(&:to_sym) }
8
8
  end
9
9
 
10
10
  describe ".weights" do
11
11
  let(:experiment) { AbPanel.experiments.first }
12
12
  subject { AbPanel.weights(experiment) }
13
13
 
14
- it { should == [25, 25, 25, 25] }
14
+ it { is_expected.to eq [25, 25, 25, 25] }
15
15
 
16
16
  describe "With a nonexistent experiment" do
17
17
  let(:experiment) { :does_not_exist }
@@ -27,7 +27,7 @@ describe AbPanel do
27
27
 
28
28
  let(:experiment) { AbPanel.experiments.first }
29
29
 
30
- it { should =~ %w( scenario1 scenario2 scenario3 original ).map(&:to_sym) }
30
+ it { is_expected.to match_array %w( scenario1 scenario2 scenario3 original ).map(&:to_sym) }
31
31
 
32
32
  describe "With an nonexistent experiment" do
33
33
  let(:experiment) { :does_not_exist }
@@ -41,8 +41,8 @@ describe AbPanel do
41
41
  describe ".conditions" do
42
42
  subject { AbPanel.conditions.experiment1 }
43
43
 
44
- it { should respond_to :scenario1? }
45
- it { should respond_to :original? }
44
+ it { is_expected.to respond_to :scenario1? }
45
+ it { is_expected.to respond_to :original? }
46
46
 
47
47
  describe 'uniqueness' do
48
48
  let(:conditions) do
@@ -54,10 +54,10 @@ describe AbPanel do
54
54
  ]
55
55
  end
56
56
 
57
- it { conditions.any?.should be true }
58
- it { conditions.all?.should be false }
59
- it { conditions.select{|c| c}.size.should be 1 }
60
- it { conditions.reject{|c| c}.size.should be 3 }
57
+ it { expect(conditions.any?).to be true }
58
+ it { expect(conditions.all?).to be false }
59
+ it { expect(conditions.select{|c| c}.size).to be 1 }
60
+ it { expect(conditions.reject{|c| c}.size).to be 3 }
61
61
  end
62
62
  end
63
63
 
@@ -72,24 +72,24 @@ describe AbPanel do
72
72
 
73
73
  it 'adds a funnel' do
74
74
  AbPanel.add_funnel('search')
75
- AbPanel.funnels.to_a.should == ['search']
75
+ expect(AbPanel.funnels.to_a).to eq ['search']
76
76
  end
77
77
 
78
78
  it 'only adds a funnel when present' do
79
79
  AbPanel.add_funnel(nil)
80
- AbPanel.funnels.to_a.should == []
80
+ expect(AbPanel.funnels.to_a).to eq []
81
81
  end
82
82
 
83
83
  it 'does not add a funnel twice' do
84
84
  AbPanel.add_funnel('search')
85
85
  AbPanel.add_funnel('search')
86
- AbPanel.funnels.to_a.should == ['search']
86
+ expect(AbPanel.funnels.to_a).to eq ['search']
87
87
  end
88
88
 
89
89
  it 'sets funnels' do
90
90
  funnels = Set.new ['search', 'cta']
91
91
  AbPanel.funnels = funnels
92
- AbPanel.funnels.to_a.should == funnels.to_a
92
+ expect(AbPanel.funnels.to_a).to eq funnels.to_a
93
93
  end
94
94
  end
95
95
 
data/spec/array_spec.rb CHANGED
@@ -3,47 +3,47 @@ require 'spec_helper'
3
3
  describe Array do
4
4
  describe '.weighted_sample' do
5
5
  before do
6
- Kernel.stub(:rand) { 0.5 }
6
+ allow(Kernel).to receive(:rand) { 0.5 }
7
7
  end
8
8
 
9
9
  context "Stub test" do
10
10
  subject { Kernel.rand }
11
- it { should eq 0.5 }
11
+ it { is_expected.to eq 0.5 }
12
12
  end
13
13
 
14
14
  let(:array) { [1, 2, 3, 4] }
15
15
  subject { array.weighted_sample }
16
16
 
17
- it { should eq 3 }
17
+ it { is_expected.to eq 3 }
18
18
 
19
19
  context "different random" do
20
20
  before do
21
- Kernel.stub(:rand) { 0 }
21
+ allow(Kernel).to receive(:rand) { 0 }
22
22
  end
23
23
 
24
- it { should eq 1 }
24
+ it { is_expected.to eq 1 }
25
25
  end
26
26
 
27
27
  context "different random" do
28
28
  before do
29
- Kernel.stub(:rand) { 1 }
29
+ allow(Kernel).to receive(:rand) { 1 }
30
30
  end
31
31
 
32
- it { should eq 4 }
32
+ it { is_expected.to eq 4 }
33
33
  end
34
34
 
35
35
  context "with weights" do
36
36
  subject { array.weighted_sample([1, 0, 0, 0]) }
37
- it { should eq 1 }
37
+ it { is_expected.to eq 1 }
38
38
  end
39
-
39
+
40
40
  context "all the same weights" do
41
- before { Kernel.stub(:rand) { 1 } }
41
+ before { allow(Kernel).to receive(:rand) { 1 } }
42
42
  subject { array.weighted_sample([0, 0, 0, 0]) }
43
- it { should eq 4 }
43
+ it { is_expected.to eq 4 }
44
44
  context "random 0" do
45
- before { Kernel.stub(:rand) { 0 } }
46
- it { should eq 1 }
45
+ before { allow(Kernel).to receive(:rand) { 0 } }
46
+ it { is_expected.to eq 1 }
47
47
  end
48
48
  end
49
49
  end
data/spec/spec_helper.rb CHANGED
@@ -5,4 +5,3 @@ require 'active_support/all'
5
5
  require File.join(File.dirname(__FILE__), "../lib", "ab_panel")
6
6
 
7
7
  Dir[File.expand_path(File.join(File.dirname(__FILE__),'support','**','*.rb'))].each {|f| require f}
8
-
@@ -2,7 +2,7 @@ require 'rails'
2
2
 
3
3
  RSpec.configure do |c|
4
4
  c.before do
5
- Rails.stub(:root) { File.expand_path( '../files', __FILE__ ) }
6
- Rails.stub(:env) { 'test' }
5
+ allow(Rails).to receive(:root) { File.expand_path( '../files', __FILE__ ) }
6
+ allow(Rails).to receive(:env) { 'test' }
7
7
  end
8
8
  end
metadata CHANGED
@@ -1,16 +1,20 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ab_panel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: 0.4.4
5
5
  platform: ruby
6
6
  authors:
7
- - Wouter de Vos
7
+ - Dennis Paagman
8
+ - Eugene Pimenov
9
+ - Jordy van Gelder
8
10
  - Mark Mulder
9
11
  - Peter de Ruijter
10
- autorequire:
12
+ - Tim Flapper
13
+ - Wouter de Vos
14
+ autorequire:
11
15
  bindir: bin
12
16
  cert_chain: []
13
- date: 2015-08-11 00:00:00.000000000 Z
17
+ date: 2021-07-01 00:00:00.000000000 Z
14
18
  dependencies:
15
19
  - !ruby/object:Gem::Dependency
16
20
  name: bundler
@@ -27,21 +31,21 @@ dependencies:
27
31
  - !ruby/object:Gem::Version
28
32
  version: '1.3'
29
33
  - !ruby/object:Gem::Dependency
30
- name: rails
34
+ name: rake
31
35
  requirement: !ruby/object:Gem::Requirement
32
36
  requirements:
33
- - - "~>"
37
+ - - ">="
34
38
  - !ruby/object:Gem::Version
35
- version: '3.2'
39
+ version: '0'
36
40
  type: :development
37
41
  prerelease: false
38
42
  version_requirements: !ruby/object:Gem::Requirement
39
43
  requirements:
40
- - - "~>"
44
+ - - ">="
41
45
  - !ruby/object:Gem::Version
42
- version: '3.2'
46
+ version: '0'
43
47
  - !ruby/object:Gem::Dependency
44
- name: rake
48
+ name: fakeweb
45
49
  requirement: !ruby/object:Gem::Requirement
46
50
  requirements:
47
51
  - - ">="
@@ -55,7 +59,7 @@ dependencies:
55
59
  - !ruby/object:Gem::Version
56
60
  version: '0'
57
61
  - !ruby/object:Gem::Dependency
58
- name: fakeweb
62
+ name: rspec
59
63
  requirement: !ruby/object:Gem::Requirement
60
64
  requirements:
61
65
  - - ">="
@@ -69,7 +73,7 @@ dependencies:
69
73
  - !ruby/object:Gem::Version
70
74
  version: '0'
71
75
  - !ruby/object:Gem::Dependency
72
- name: rspec
76
+ name: byebug
73
77
  requirement: !ruby/object:Gem::Requirement
74
78
  requirements:
75
79
  - - ">="
@@ -83,19 +87,19 @@ dependencies:
83
87
  - !ruby/object:Gem::Version
84
88
  version: '0'
85
89
  - !ruby/object:Gem::Dependency
86
- name: byebug
90
+ name: rails
87
91
  requirement: !ruby/object:Gem::Requirement
88
92
  requirements:
89
93
  - - ">="
90
94
  - !ruby/object:Gem::Version
91
- version: '0'
92
- type: :development
95
+ version: '4.0'
96
+ type: :runtime
93
97
  prerelease: false
94
98
  version_requirements: !ruby/object:Gem::Requirement
95
99
  requirements:
96
100
  - - ">="
97
101
  - !ruby/object:Gem::Version
98
- version: '0'
102
+ version: '4.0'
99
103
  - !ruby/object:Gem::Dependency
100
104
  name: mixpanel
101
105
  requirement: !ruby/object:Gem::Requirement
@@ -110,11 +114,8 @@ dependencies:
110
114
  - - ">="
111
115
  - !ruby/object:Gem::Version
112
116
  version: '0'
113
- description: Run A/B test experiments on your Rails 3+ site using Mixpanel as a backend.
117
+ description: Run A/B test experiments on your Rails 4+ site using Mixpanel as a backend.
114
118
  email:
115
- - wouter@springest.com
116
- - markmulder@gmail.com
117
- - hello@thisiswho.im
118
119
  executables: []
119
120
  extensions: []
120
121
  extra_rdoc_files: []
@@ -212,7 +213,7 @@ homepage: https://github.com/Springest/ab_panel
212
213
  licenses:
213
214
  - MIT
214
215
  metadata: {}
215
- post_install_message:
216
+ post_install_message:
216
217
  rdoc_options: []
217
218
  require_paths:
218
219
  - lib
@@ -227,11 +228,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
227
228
  - !ruby/object:Gem::Version
228
229
  version: '0'
229
230
  requirements: []
230
- rubyforge_project:
231
- rubygems_version: 2.2.2
232
- signing_key:
231
+ rubygems_version: 3.0.3
232
+ signing_key:
233
233
  specification_version: 4
234
- summary: Run A/B test experiments on your Rails 3+ site using Mixpanel as a backend.
234
+ summary: Run A/B test experiments on your Rails 4+ site using Mixpanel as a backend.
235
235
  test_files:
236
236
  - example/.gitignore
237
237
  - example/Gemfile