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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 424e1945f8aaf1315085953f1795186ee0c7caf4
4
- data.tar.gz: 3415e4788d0c2ed9802532212a74a1b87837d888
3
+ metadata.gz: cf7115b71744ec2229a2d850f8b6a4efecd79d28
4
+ data.tar.gz: 0f5afa558a4412a10db629f0c448d4647c0959b3
5
5
  SHA512:
6
- metadata.gz: cdb2d36abb5bc62777410cb7d97043f8271537d224182081c4d6e0db4a2b8d774c030ddd33a1a3d27fe37ef21125f66ded5a77a00fb08d86599835eb37a136a3
7
- data.tar.gz: 2770754f7379de39c788f626c441869477905bb6e90ebcefe007efc596f48e5b4d543d7b2403688f93e4eac3b6a88e7dcdfc36f458c4fe3f21063b333d4609b5
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
@@ -1,11 +1,30 @@
1
1
  module Detour::Flaggable
2
- module ClassMethods
3
- # Finds a record by the field set by the :find_by param in
4
- # `acts_as_flaggable`. If no :find_by param was provided, :id is used.
5
- #
6
- # @param [String,Integer] value The value to find the record by.
7
- def flaggable_find!(value)
8
- send("find_by_#{@detour_flaggable_find_by}!", value)
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
- if detour_features.include? feature_name.to_s
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
@@ -1,3 +1,3 @@
1
1
  module Detour
2
- VERSION = "0.0.10"
2
+ VERSION = "0.0.11"
3
3
  end
@@ -1,5 +1,6 @@
1
1
  FactoryGirl.define do
2
+
2
3
  factory :feature, class: "Detour::Feature" do
3
- name "foo_feature"
4
+ sequence(:name) { |n| "#{n}_feature" }
4
5
  end
5
6
  end
@@ -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 { User.new }
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 }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: detour
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.10
4
+ version: 0.0.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonathan Clem