detour 0.0.10 → 0.0.11
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/app/models/detour/concerns/matchers.rb +0 -33
- data/lib/detour/acts_as_flaggable.rb +0 -5
- data/lib/detour/flaggable.rb +37 -24
- data/lib/detour/version.rb +1 -1
- data/spec/factories/feature.rb +2 -1
- data/spec/lib/detour/acts_as_flaggable_spec.rb +0 -1
- data/spec/lib/detour/flaggable_spec.rb +31 -12
- data/spec/models/detour/feature_spec.rb +0 -48
- 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: cf7115b71744ec2229a2d850f8b6a4efecd79d28
|
4
|
+
data.tar.gz: 0f5afa558a4412a10db629f0c448d4647c0959b3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8b37642c8dd68bd34f924dcc5438c847c9c4dde889a91e1d32afe5375b4de3aee2ff8d6c04c9b9fc34a892c7d79402cd5f7fdabb42bb4054ad15daa37152700e
|
7
|
+
data.tar.gz: a2f4afa256166f2f97b12f52bb0853c60a9e9674d2f83dd34b214caf30a7736042706ca9f2479b790f4fabb77219ba006778e38eeec72abe4374857497cd106a
|
@@ -1,38 +1,5 @@
|
|
1
1
|
module Detour::Concerns
|
2
2
|
module Matchers
|
3
|
-
# Determines whether or not the given instance has had the feature rolled out
|
4
|
-
# to it either via direct flagging-in, percentage, or by database or defined
|
5
|
-
# group membership.
|
6
|
-
#
|
7
|
-
# @example
|
8
|
-
# feature.match?(current_user)
|
9
|
-
#
|
10
|
-
# @param [ActiveRecord::Base] instance A record to be tested for feature
|
11
|
-
# rollout.
|
12
|
-
#
|
13
|
-
# @return Whether or not the given instance has the feature rolled out to it.
|
14
|
-
def match?(instance)
|
15
|
-
match_id?(instance) ||
|
16
|
-
match_percentage?(instance) ||
|
17
|
-
match_database_groups?(instance) ||
|
18
|
-
match_defined_groups?(instance)
|
19
|
-
end
|
20
|
-
|
21
|
-
# Determines whether or not the given instance has had the feature rolled out
|
22
|
-
# to it via direct flagging-in.
|
23
|
-
#
|
24
|
-
# @example
|
25
|
-
# feature.match_id?(current_user)
|
26
|
-
#
|
27
|
-
# @param [ActiveRecord::Base] instance A record to be tested for feature
|
28
|
-
# rollout.
|
29
|
-
#
|
30
|
-
# @return Whether or not the given instance has the feature rolled out to it
|
31
|
-
# via direct flagging-in.
|
32
|
-
def match_id?(instance)
|
33
|
-
flag_in_flags.where(flaggable_type: instance.class.to_s, flaggable_id: instance.id).any?
|
34
|
-
end
|
35
|
-
|
36
3
|
# Determines whether or not the given instance has had the feature rolled out
|
37
4
|
# to it via percentage.
|
38
5
|
#
|
@@ -71,10 +71,6 @@ module Detour::ActsAsFlaggable
|
|
71
71
|
as: :flaggable,
|
72
72
|
class_name: "Detour::OptOutFlag"
|
73
73
|
|
74
|
-
has_many :features,
|
75
|
-
through: :flag_in_flags,
|
76
|
-
class_name: "Detour::Feature"
|
77
|
-
|
78
74
|
if options[:find_by]
|
79
75
|
@detour_flaggable_find_by = options[:find_by]
|
80
76
|
end
|
@@ -83,7 +79,6 @@ module Detour::ActsAsFlaggable
|
|
83
79
|
@detour_flaggable_find_by
|
84
80
|
end
|
85
81
|
|
86
|
-
extend Detour::Flaggable::ClassMethods
|
87
82
|
include Detour::Flaggable
|
88
83
|
end
|
89
84
|
end
|
data/lib/detour/flaggable.rb
CHANGED
@@ -1,11 +1,30 @@
|
|
1
1
|
module Detour::Flaggable
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
# Returns an array of all features rolled out to the given record.
|
5
|
+
#
|
6
|
+
# @example
|
7
|
+
# user.features
|
8
|
+
#
|
9
|
+
# @return [Array] An array of {Detour::Feature}s.
|
10
|
+
def features
|
11
|
+
@features ||= begin
|
12
|
+
@features = []
|
13
|
+
|
14
|
+
opt_out_ids = opt_out_flags.map(&:feature_id) + [-1] # prevents "NOT IN (NULL)"
|
15
|
+
table_name = self.class.table_name
|
16
|
+
|
17
|
+
database_group_features = Detour::Feature.joins(:"#{table_name}_database_group_flags" => :memberships).where("detour_memberships" => { member_id: self.id }).where("'detour_features'.id NOT IN (?)", opt_out_ids)
|
18
|
+
@features.concat database_group_features
|
19
|
+
|
20
|
+
defined_group_features = Detour::Feature.joins(:"#{table_name}_defined_group_flags").where("'detour_features'.id NOT IN (?)", opt_out_ids)
|
21
|
+
@features.concat defined_group_features.select { |feature| feature.match_defined_groups?(self) }
|
22
|
+
|
23
|
+
percentage_group_features = Detour::Feature.joins(:"#{table_name}_percentage_flag").where("'detour_features'.id NOT IN (?)", opt_out_ids)
|
24
|
+
@features.concat percentage_group_features.select { |feature| feature.match_percentage?(self) }
|
25
|
+
|
26
|
+
flag_in_features = Detour::Feature.joins(:"#{table_name}_flag_ins").where("'detour_features'.id NOT IN (?)", opt_out_ids)
|
27
|
+
@features.concat flag_in_features
|
9
28
|
end
|
10
29
|
end
|
11
30
|
|
@@ -22,26 +41,20 @@ module Detour::Flaggable
|
|
22
41
|
# @param [Proc] &block A block to be called if the user is flagged in to the
|
23
42
|
# feature.
|
24
43
|
def has_feature?(feature_name, &block)
|
25
|
-
|
26
|
-
match = true
|
27
|
-
else
|
28
|
-
feature = Detour::Feature.find_by_name(feature_name)
|
29
|
-
return false unless feature
|
30
|
-
|
31
|
-
opt_out = opt_out_flags.find_by_feature_id(feature.id)
|
32
|
-
return false if opt_out
|
33
|
-
|
34
|
-
match = feature.match? self
|
35
|
-
|
36
|
-
if match
|
37
|
-
detour_features << feature.name.to_s
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
match
|
44
|
+
features.map(&:name).include? feature_name.to_s
|
42
45
|
end
|
43
46
|
|
44
47
|
def detour_features
|
45
48
|
@detour_features ||= []
|
46
49
|
end
|
50
|
+
|
51
|
+
included do
|
52
|
+
# Finds a record by the field set by the :find_by param in
|
53
|
+
# `acts_as_flaggable`. If no :find_by param was provided, :id is used.
|
54
|
+
#
|
55
|
+
# @param [String,Integer] value The value to find the record by.
|
56
|
+
def self.flaggable_find!(value)
|
57
|
+
send("find_by_#{@detour_flaggable_find_by}!", value)
|
58
|
+
end
|
59
|
+
end
|
47
60
|
end
|
data/lib/detour/version.rb
CHANGED
data/spec/factories/feature.rb
CHANGED
@@ -5,7 +5,6 @@ describe Detour::ActsAsFlaggable do
|
|
5
5
|
|
6
6
|
it { should have_many :flag_in_flags }
|
7
7
|
it { should have_many :opt_out_flags }
|
8
|
-
it { should have_many(:features).through(:flag_in_flags) }
|
9
8
|
|
10
9
|
it "includes Detour::Flaggable" do
|
11
10
|
subject.class.ancestors.should include Detour::Flaggable
|
@@ -1,7 +1,37 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe Detour::Flaggable do
|
4
|
-
subject {
|
4
|
+
subject { create :user }
|
5
|
+
|
6
|
+
describe "#features" do
|
7
|
+
let(:feature1) { create :feature }
|
8
|
+
let(:feature2) { create :feature }
|
9
|
+
let(:feature3) { create :feature }
|
10
|
+
let(:feature4) { create :feature }
|
11
|
+
let(:feature5) { create :feature }
|
12
|
+
let(:membership) { create :membership, member: subject }
|
13
|
+
let(:defined_group) { Detour::DefinedGroup.new "foo", ->(user){true} }
|
14
|
+
|
15
|
+
before do
|
16
|
+
Detour.config.defined_groups["User"] = { foo: defined_group }
|
17
|
+
create :flag_in_flag, flaggable: subject, feature: feature1
|
18
|
+
create :percentage_flag, flaggable_type: "User", feature: feature2
|
19
|
+
create :database_group_flag, flaggable_type: "User", feature: feature3, group: membership.group
|
20
|
+
create :database_group_flag, flaggable_type: "User", feature: feature4, group: membership.group
|
21
|
+
create :opt_out_flag, flaggable: subject, feature: feature4
|
22
|
+
create :defined_group_flag, flaggable_type: "User", feature: feature5, group_name: "foo"
|
23
|
+
end
|
24
|
+
|
25
|
+
it "finds every feature for a record" do
|
26
|
+
subject.features.sort.should eq [feature1, feature2, feature3, feature5].sort
|
27
|
+
end
|
28
|
+
|
29
|
+
it "is memoized" do
|
30
|
+
subject.features
|
31
|
+
Detour::Feature.stub(:joins) { raise "I was called" }
|
32
|
+
subject.features
|
33
|
+
end
|
34
|
+
end
|
5
35
|
|
6
36
|
describe "#flaggable_find!" do
|
7
37
|
context "when a non-default find_by is not specified" do
|
@@ -27,17 +57,6 @@ describe Detour::Flaggable do
|
|
27
57
|
let(:user) { create :user }
|
28
58
|
let(:feature) { create :feature }
|
29
59
|
|
30
|
-
it "memoizes found features" do
|
31
|
-
Detour::Feature.stub(:find_by_name) { feature }
|
32
|
-
feature.flag_in_flags.create(flaggable: user)
|
33
|
-
|
34
|
-
feature.should_receive(:match?).with(user).and_return(true)
|
35
|
-
user.has_feature?(feature.name)
|
36
|
-
|
37
|
-
feature.should_not_receive(:match?).with(user)
|
38
|
-
user.has_feature?(feature.name)
|
39
|
-
end
|
40
|
-
|
41
60
|
context "when the user is not flagged in" do
|
42
61
|
it "returns false" do
|
43
62
|
user.has_feature?(feature.name).should be_false
|
@@ -97,31 +97,6 @@ describe Detour::Feature do
|
|
97
97
|
end
|
98
98
|
end
|
99
99
|
|
100
|
-
describe "#match?" do
|
101
|
-
let(:user) { create :user }
|
102
|
-
let(:feature) { create :feature }
|
103
|
-
|
104
|
-
it "checks if the user is flagged individually" do
|
105
|
-
feature.should_receive(:match_id?).with(user)
|
106
|
-
feature.match?(user)
|
107
|
-
end
|
108
|
-
|
109
|
-
it "checks if the user is flagged as part of a percentage" do
|
110
|
-
feature.should_receive(:match_percentage?).with(user)
|
111
|
-
feature.match?(user)
|
112
|
-
end
|
113
|
-
|
114
|
-
it "checks if the user is flagged as part of a database group" do
|
115
|
-
feature.should_receive(:match_database_groups?).with(user)
|
116
|
-
feature.match?(user)
|
117
|
-
end
|
118
|
-
|
119
|
-
it "checks if the user is flagged as part of a defined group" do
|
120
|
-
feature.should_receive(:match_defined_groups?).with(user)
|
121
|
-
feature.match?(user)
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
100
|
describe "#flag_in_count_for" do
|
126
101
|
context "when a value does not exist" do
|
127
102
|
let(:feature) { create :feature }
|
@@ -158,29 +133,6 @@ describe Detour::Feature do
|
|
158
133
|
end
|
159
134
|
end
|
160
135
|
|
161
|
-
|
162
|
-
describe "#match_id?" do
|
163
|
-
let(:user) { create :user }
|
164
|
-
let(:user2) { create :user }
|
165
|
-
let(:feature) { create :feature }
|
166
|
-
|
167
|
-
before do
|
168
|
-
create(:flag_in_flag, flaggable: user, feature: feature)
|
169
|
-
end
|
170
|
-
|
171
|
-
context "when the feature exists for the instance" do
|
172
|
-
it "returns true" do
|
173
|
-
feature.match_id?(user).should be_true
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
context "when the feature does not exist for the instance" do
|
178
|
-
it "returns false" do
|
179
|
-
feature.match_id?(user2).should be_false
|
180
|
-
end
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
136
|
describe "#match_percentage?" do
|
185
137
|
let(:user) { create :user }
|
186
138
|
let(:feature) { create :feature }
|