easy_ab 0.3.0 → 0.4.0
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/CHANGELOG.md +9 -6
- data/app/models/easy_ab/grouping.rb +7 -1
- data/lib/easy_ab/experiment.rb +23 -17
- data/lib/easy_ab/helpers.rb +33 -6
- data/lib/easy_ab/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 068d106a909b0229bc7fc28960f275fca34bd5e9
|
4
|
+
data.tar.gz: 411b8a8f520e4d4f1dd627065e1105b08175acee
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4429ad954dcf221b315d43766c04446e72ee1bb21cef672510e1aebd17214d9224b0a20fa0af06755f52e8818c6da1f1cca317827085fe8c6b03ee956701cb8f
|
7
|
+
data.tar.gz: 01924f52c1e3a40dde96fcfee2bf8e5d39b79b2f16df5b8c55a4a51e71e471ae60984a2452a06a8e6b51d03654c6d1e3ee539db45a141219b91a742e0e600916
|
data/CHANGELOG.md
CHANGED
@@ -1,14 +1,17 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# 0.4.0 (2017-08-16)
|
2
|
+
- You can specify user in `ab_test()` This useful when requests do not contain current_user. A well-known example is controllers which handle payment results by listening requests from 3rd party payment gateway.
|
3
|
+
|
4
|
+
# 0.3.0 (2017-08-16)
|
5
|
+
- Supports scope in config to define whether a user can join an experiment or not.
|
3
6
|
|
4
7
|
# 0.2.0 (2017-08-15)
|
5
|
-
|
8
|
+
- **API change**: If all rules failed, `ab_test` returns nil, instead of the first variant.
|
6
9
|
|
7
10
|
# 0.1.0
|
8
|
-
|
11
|
+
- Support winner
|
9
12
|
|
10
13
|
# 0.0.3
|
11
|
-
|
14
|
+
- Add new API `all_participated_experiments` to list current user's all participated experiments
|
12
15
|
|
13
16
|
# 0.0.1
|
14
|
-
|
17
|
+
- The first version :)
|
@@ -5,7 +5,7 @@ module EasyAb
|
|
5
5
|
validates :experiment, presence: true
|
6
6
|
validates :variant, presence: true
|
7
7
|
validates :user_id, uniqueness: { scope: [:experiment] }
|
8
|
-
|
8
|
+
validate :cookie_should_be_unique_when_user_id_is_nil
|
9
9
|
validate :user_should_be_present
|
10
10
|
|
11
11
|
private
|
@@ -16,5 +16,11 @@ module EasyAb
|
|
16
16
|
errors.add(:cookie, "or user_id can't be blank")
|
17
17
|
end
|
18
18
|
end
|
19
|
+
|
20
|
+
def cookie_should_be_unique_when_user_id_is_nil
|
21
|
+
if user_id.nil?
|
22
|
+
errors.add(:cookie, "already exists") if self.class.where(cookie: cookie, user_id: nil).exists?
|
23
|
+
end
|
24
|
+
end
|
19
25
|
end
|
20
26
|
end
|
data/lib/easy_ab/experiment.rb
CHANGED
@@ -64,29 +64,35 @@ module EasyAb
|
|
64
64
|
grouping.variant
|
65
65
|
end
|
66
66
|
|
67
|
+
# TODO: add spec
|
67
68
|
def find_grouping_by_user_recognition(user_recognition)
|
68
|
-
user_id
|
69
|
-
cookie
|
69
|
+
user_id = user_recognition[:id].presence
|
70
|
+
cookie = user_recognition[:cookie].presence
|
71
|
+
raise 'User not found: both user_id and cookie are empty' if user_id.nil? && cookie.nil?
|
72
|
+
|
73
|
+
# Cases should take into consideration
|
74
|
+
# Case I: user participated experiment with login and return again
|
75
|
+
# Case II: user participated experiment with login and return by another device with login
|
76
|
+
# Case III: user participated experiment with login and return by the same device, but cookie was cleared between last and this participation
|
77
|
+
# => Both II and III already exist a record with the same user_id but different cookie
|
78
|
+
# In the above two cases, we update the cookie of the exising record
|
79
|
+
#
|
80
|
+
# Case IV: User participated experiment without login and return with login
|
81
|
+
# => Assign user_id to the existing record
|
82
|
+
#
|
83
|
+
# Case V: User participated experiment without login and return without login, too
|
70
84
|
grouping = nil
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
if user_id # If user login
|
75
|
-
# Case I: User participated experiment with login and return again
|
76
|
-
# Case II: user participated experiment with login and return by another device with login
|
77
|
-
# Case III: user participated experiment with login and return by the same device, but cookie was cleared between last and this participation
|
78
|
-
# => Both II and III already exist a record with the same user_id but different cookie
|
79
|
-
# In the above two cases, we update the cookie of the exising record
|
85
|
+
if user_id # User is signed in
|
86
|
+
# Case I, II, III
|
80
87
|
return grouping if (grouping = groupings.where(user_id: user_id).first) && ((cookie && grouping.cookie = cookie) || true)
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
88
|
+
# Case IV
|
89
|
+
return grouping if (cookie && grouping = groupings.where(user_id: nil, cookie: cookie).first) && ((grouping.user_id = user_id) || true) # Assign user_id
|
90
|
+
elsif cookie # User is not signed in
|
91
|
+
# Case V
|
85
92
|
return grouping if grouping = groupings.where(cookie: cookie).first
|
86
93
|
end
|
87
94
|
|
88
|
-
|
89
|
-
nil
|
95
|
+
grouping
|
90
96
|
end
|
91
97
|
|
92
98
|
def groupings
|
data/lib/easy_ab/helpers.rb
CHANGED
@@ -7,7 +7,7 @@ module EasyAb
|
|
7
7
|
|
8
8
|
if respond_to?(:request) && params[:ab_test] && params[:ab_test][experiment_name]
|
9
9
|
# Check current user is admin or not by proc defined by gem user
|
10
|
-
if
|
10
|
+
if easy_ab_user_is_admin?(options)
|
11
11
|
options[:variant] ||= params[:ab_test][experiment_name]
|
12
12
|
end
|
13
13
|
# TODO: exclude bot
|
@@ -15,21 +15,23 @@ module EasyAb
|
|
15
15
|
|
16
16
|
experiment = EasyAb::Experiment.find_by_name!(experiment_name)
|
17
17
|
|
18
|
-
# Obtain context
|
18
|
+
# Obtain context for rules
|
19
19
|
if experiment.rules.present?
|
20
20
|
@rules_with_current_context ||= experiment.rules.map { |rule| Proc.new { instance_exec(&rule)} }
|
21
21
|
options[:contexted_rules] = @rules_with_current_context
|
22
22
|
end
|
23
23
|
|
24
|
-
# Obtain context
|
24
|
+
# Obtain context for scope
|
25
25
|
if experiment.scope.present?
|
26
26
|
@scope ||= Proc.new { instance_exec(&experiment.scope) }
|
27
27
|
options[:scope] = @scope
|
28
28
|
end
|
29
29
|
|
30
30
|
@variant_cache ||= {}
|
31
|
-
@variant_cache[
|
32
|
-
|
31
|
+
@variant_cache[easy_ab_user_id(options)] ||= {}
|
32
|
+
@variant_cache[easy_ab_user_id(options)][experiment_name] ||= experiment.assign_variant(user_recognition, options)
|
33
|
+
variant = @variant_cache[easy_ab_user_id(options)][experiment_name]
|
34
|
+
block_given? ? yield(variant) : variant
|
33
35
|
end
|
34
36
|
|
35
37
|
# Return all participated experiments and the corresponding variants for current user
|
@@ -62,21 +64,46 @@ module EasyAb
|
|
62
64
|
# TODO:
|
63
65
|
# return (raise NotImplementedError) if options[:user] && (users << options[:user])
|
64
66
|
|
65
|
-
|
67
|
+
# if options[:user] && options[:user].id
|
68
|
+
# user_recognition[:id] = options[:user].id
|
69
|
+
# else
|
70
|
+
# user_recognition[:id] = current_user_id if current_user_signed_in?
|
71
|
+
# end
|
72
|
+
|
73
|
+
user_recognition[:id] = easy_ab_user_id(options)
|
74
|
+
|
66
75
|
# Controllers and views
|
67
76
|
user_recognition[:cookie] = find_or_create_easy_ab_cookie if respond_to?(:request)
|
68
77
|
|
69
78
|
user_recognition
|
70
79
|
end
|
71
80
|
|
81
|
+
def easy_ab_user_signed_in?
|
82
|
+
current_user_signed_in?
|
83
|
+
end
|
84
|
+
|
72
85
|
def current_user_signed_in?
|
73
86
|
user_signed_in_method_proc.call
|
74
87
|
end
|
75
88
|
|
89
|
+
def easy_ab_user_id(options)
|
90
|
+
if options[:user]
|
91
|
+
options[:user].id
|
92
|
+
elsif easy_ab_user_signed_in?
|
93
|
+
current_user_id
|
94
|
+
else
|
95
|
+
nil
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
76
99
|
def current_user_id
|
77
100
|
current_user_id_proc.call
|
78
101
|
end
|
79
102
|
|
103
|
+
def easy_ab_user_is_admin?(options)
|
104
|
+
options[:user] ? false : current_user_is_admin?
|
105
|
+
end
|
106
|
+
|
80
107
|
def current_user_is_admin?
|
81
108
|
authorize_admin_with_proc.call
|
82
109
|
end
|
data/lib/easy_ab/version.rb
CHANGED