togls 3.0.0.pre.rc.2 → 3.0.0.pre.rc.3
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 +1 -0
- data/README.md +50 -10
- data/lib/togls/feature_toggle_registry_manager.rb +2 -42
- data/lib/togls/rule_manager.rb +53 -0
- data/lib/togls/rule_repository.rb +5 -5
- data/lib/togls/toggle_repository.rb +3 -4
- data/lib/togls/version.rb +1 -1
- data/lib/togls.rb +2 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 05024ddd358a85a71a6c2a321ca23e6dc1f1a54f
|
4
|
+
data.tar.gz: c0cffcdf9ac3c88225383dd052ebf02497a9d43e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fcc5a4843465954f936decf0da23c2bdd16fd6683634a791905d700bb18753142b226653d1fcf60b8f695cef103a7f95df81e0d37afce3d9bb58bdcea1d7deff
|
7
|
+
data.tar.gz: 73bd020d13232d401c8b0dc77bcff6096a27b16674a4c5f49710cd093b2817a4287ccedca149213cce81de7ddbc3ae853ab7b874af5d015111005253a8d96f5c
|
data/CHANGELOG.md
CHANGED
@@ -10,6 +10,7 @@ that you can set version constraints properly.
|
|
10
10
|
|
11
11
|
#### [Unreleased] - now
|
12
12
|
|
13
|
+
* `Changed`: Rule and Rule Type management to be global under Togls
|
13
14
|
* `Changed`: The testing interface to allow for contract enforcement in tests
|
14
15
|
and allow altering existing feature rules within tests.
|
15
16
|
* `Added`: `Togls.rule` method to simplify rule construction from `type_id`
|
data/README.md
CHANGED
@@ -52,13 +52,28 @@ how one would define some basic feature toggles.
|
|
52
52
|
```ruby
|
53
53
|
Togls.release do
|
54
54
|
# Set this feature to always be on
|
55
|
-
feature(:pop_up_login_form, "use pop up login instead of normal login").on
|
55
|
+
feature(:pop_up_login_form, "use pop up login instead of normal login").on
|
56
56
|
|
57
57
|
# Set this feature to always be off
|
58
58
|
feature(:send_follup_email, "send the follow up email").off
|
59
59
|
end
|
60
60
|
```
|
61
61
|
|
62
|
+
The above defined feature toggles would use
|
63
|
+
[default feature target type](https://github.com/codebreakdown/togls/wiki/Abstract-Target-Types#setting-the-default-feature-target-type).
|
64
|
+
If we wanted to define them explicitly with other target types it would like as
|
65
|
+
follows.
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
Togls.release do
|
69
|
+
# Set this feature to always be on
|
70
|
+
feature(:pop_up_login_form, "use pop up login instead of normal login", :user_id).on
|
71
|
+
|
72
|
+
# Set this feature to always be off
|
73
|
+
feature(:send_follup_email, "send the follow up email", :user_email_address).off
|
74
|
+
end
|
75
|
+
```
|
76
|
+
|
62
77
|
### Evaluating Feature Toggles
|
63
78
|
|
64
79
|
Once you have defined your feature toggles. The next thing you would
|
@@ -83,6 +98,28 @@ end
|
|
83
98
|
**Note:** Feature toggles that are evaluated but have **not** been
|
84
99
|
defined will default to **off**.
|
85
100
|
|
101
|
+
The above two feature toggles evaluated are written as if the feature toggle has
|
102
|
+
a target type of `Togls::TargetTypes::NONE`. If the feature toggles had a
|
103
|
+
specific target type and they were evaluted as shown above an exception would be
|
104
|
+
raised notifying you that they expect an entity of that type as the target for
|
105
|
+
evaluation. To better match the explicit target type example from Defining
|
106
|
+
Feature Toggles it would look something like the following.
|
107
|
+
|
108
|
+
|
109
|
+
```ruby
|
110
|
+
if Togls.feature(:pop_up_login_form).on?(current_user.id)
|
111
|
+
# Use pop up login form
|
112
|
+
else
|
113
|
+
# Use normal non-pop up login form
|
114
|
+
end
|
115
|
+
|
116
|
+
...
|
117
|
+
|
118
|
+
if Togls.feature(:send_follup_email).on?(current_user.email)
|
119
|
+
# send the follow up email
|
120
|
+
end
|
121
|
+
```
|
122
|
+
|
86
123
|
### Override Feature Toggles
|
87
124
|
|
88
125
|
Toggles can be overriden using environment variables following the
|
@@ -106,7 +143,11 @@ We could override this by setting the value of the
|
|
106
143
|
to override a feature toggle to an on state you can set the
|
107
144
|
`TOGLS_POP_UP_LOGIN_FORM` environment variable to `"true"`.
|
108
145
|
|
109
|
-
|
146
|
+
**Note:** This feature is explicitly designed for use in your development
|
147
|
+
environment. If you use this feature in other environments (qa, staging,
|
148
|
+
production, etc.) it may not behave as you expect.
|
149
|
+
|
150
|
+
### Toggle Features based on Group Membership
|
110
151
|
|
111
152
|
`togls` provides out of the box support for toggling features based on
|
112
153
|
group membership. This basically allows you to have a feature **on** for
|
@@ -115,10 +156,10 @@ extremely useful if you want to enable features for a small alpha test
|
|
115
156
|
group for example.
|
116
157
|
|
117
158
|
**Note:** This is implemented using `togls` extremely robust [custom
|
118
|
-
rules](https://github.com/codebreakdown/togls/wiki/Custom-Rules) system.
|
159
|
+
rules](https://github.com/codebreakdown/togls/wiki/Custom-Rule-Types-&-Rules) system.
|
119
160
|
The following example is just one of the many powerful things you can do
|
120
161
|
with `togls` and [custom
|
121
|
-
rules](https://github.com/codebreakdown/togls/wiki/Custom-Rules).
|
162
|
+
rules](https://github.com/codebreakdown/togls/wiki/Custom-Rule-Types-&-Rules).
|
122
163
|
|
123
164
|
#### Defining Group based Feature Toggles
|
124
165
|
|
@@ -128,11 +169,10 @@ based on group membership.
|
|
128
169
|
```ruby
|
129
170
|
# Create a group rule so the feature is on if the user is a member of
|
130
171
|
# the group.
|
131
|
-
alpha_testers = Togls
|
132
|
-
"user2@example.com"])
|
172
|
+
alpha_testers = Togls.rule(:group, ["user1@email.com", "user2@example.com"], target_type: :user_email_address)
|
133
173
|
|
134
174
|
Togls.release do
|
135
|
-
feature(:new_contact_form, "use new contact form").on(alpha_testers)
|
175
|
+
feature(:new_contact_form, "use new contact form", target_type: :user_email_address).on(alpha_testers)
|
136
176
|
end
|
137
177
|
```
|
138
178
|
|
@@ -181,10 +221,10 @@ in the example above and it would look something like the following:
|
|
181
221
|
```ruby
|
182
222
|
# Create a group rule so the feature is on if the user is a member of
|
183
223
|
# the group.
|
184
|
-
alpha_testers = Togls
|
224
|
+
alpha_testers = Togls.rule(:group, [1, 23, 42, 83], :user_id)
|
185
225
|
|
186
226
|
Togls.release do
|
187
|
-
feature(:new_contact_form, "use new contact form").on(alpha_testers)
|
227
|
+
feature(:new_contact_form, "use new contact form", :user_id).on(alpha_testers)
|
188
228
|
end
|
189
229
|
```
|
190
230
|
|
@@ -213,7 +253,7 @@ Toggles](https://github.com/codebreakdown/togls/wiki/Testing-with-Toggles),
|
|
213
253
|
[Provided Rules
|
214
254
|
Reference](https://github.com/codebreakdown/togls/wiki/Provided-Rules-Reference),
|
215
255
|
[Custom
|
216
|
-
Rules](https://github.com/codebreakdown/togls/wiki/Custom-Rules),
|
256
|
+
Rules](https://github.com/codebreakdown/togls/wiki/Custom-Rule-Types-&-Rules),
|
217
257
|
[Organize Toggle
|
218
258
|
Definitions](https://github.com/codebreakdown/togls/wiki/Organize-Toggle-Definitions),
|
219
259
|
[Creating Additional Toggle
|
@@ -24,19 +24,6 @@ module Togls
|
|
24
24
|
@release_blocks ||= []
|
25
25
|
end
|
26
26
|
|
27
|
-
def rule_types(&block)
|
28
|
-
rule_type_registry.expand(&block) if block
|
29
|
-
rule_type_registry
|
30
|
-
end
|
31
|
-
|
32
|
-
def rule_type(type_id)
|
33
|
-
rule_type_registry.get(type_id)
|
34
|
-
end
|
35
|
-
|
36
|
-
def rule(type_id, data, target_type: Togls::TargetTypes::NOT_SET)
|
37
|
-
rule_type(type_id).new(type_id, data, target_type: target_type)
|
38
|
-
end
|
39
|
-
|
40
27
|
def feature(key)
|
41
28
|
Toggler.new(release_toggle_registry.instance_variable_get(:@toggle_repository), release_toggle_registry.get(key))
|
42
29
|
end
|
@@ -62,38 +49,17 @@ module Togls
|
|
62
49
|
|
63
50
|
private
|
64
51
|
|
65
|
-
def rule_type_repository
|
66
|
-
if @rule_type_repository.nil?
|
67
|
-
rule_type_repository_drivers = [RuleTypeRepositoryDrivers::InMemoryDriver.new]
|
68
|
-
@rule_type_repository = RuleTypeRepository.new(rule_type_repository_drivers)
|
69
|
-
end
|
70
|
-
@rule_type_repository
|
71
|
-
end
|
72
|
-
|
73
|
-
def rule_type_registry
|
74
|
-
if @rule_type_registry.nil?
|
75
|
-
@rule_type_registry = RuleTypeRegistry.new(rule_type_repository)
|
76
|
-
@rule_type_registry.register(:boolean, Togls::Rules::Boolean)
|
77
|
-
@rule_type_registry.register(:group, Togls::Rules::Group)
|
78
|
-
end
|
79
|
-
@rule_type_registry
|
80
|
-
end
|
81
|
-
|
82
52
|
def test_toggle_registry
|
83
53
|
feature_repository_drivers =
|
84
54
|
[Togls::FeatureRepositoryDrivers::InMemoryDriver.new]
|
85
55
|
test_feature_repository = Togls::FeatureRepository.new(
|
86
56
|
feature_repository_drivers)
|
87
57
|
|
88
|
-
rule_repository_drivers =
|
89
|
-
[Togls::RuleRepositoryDrivers::InMemoryDriver.new]
|
90
|
-
rule_repository = Togls::RuleRepository.new(rule_type_registry, rule_repository_drivers)
|
91
|
-
|
92
58
|
toggle_repository_drivers = [
|
93
59
|
Togls::ToggleRepositoryDrivers::InMemoryDriver.new]
|
94
60
|
|
95
61
|
toggle_repository = Togls::ToggleRepository.new(
|
96
|
-
toggle_repository_drivers, test_feature_repository
|
62
|
+
toggle_repository_drivers, test_feature_repository)
|
97
63
|
|
98
64
|
tr = ToggleRegistry.new(test_feature_repository, toggle_repository)
|
99
65
|
release_blocks.each do |p|
|
@@ -105,12 +71,6 @@ module Togls
|
|
105
71
|
|
106
72
|
def release_toggle_registry
|
107
73
|
if @release_toggle_registry.nil?
|
108
|
-
rule_repository_drivers = [
|
109
|
-
Togls::RuleRepositoryDrivers::InMemoryDriver.new,
|
110
|
-
Togls::RuleRepositoryDrivers::EnvOverrideDriver.new
|
111
|
-
]
|
112
|
-
|
113
|
-
rule_repository = Togls::RuleRepository.new(rule_type_registry, rule_repository_drivers)
|
114
74
|
|
115
75
|
toggle_repository_drivers = [
|
116
76
|
Togls::ToggleRepositoryDrivers::InMemoryDriver.new,
|
@@ -118,7 +78,7 @@ module Togls
|
|
118
78
|
]
|
119
79
|
|
120
80
|
toggle_repository = Togls::ToggleRepository.new(
|
121
|
-
toggle_repository_drivers, feature_repository
|
81
|
+
toggle_repository_drivers, feature_repository)
|
122
82
|
|
123
83
|
@release_toggle_registry = ToggleRegistry.new(feature_repository,
|
124
84
|
toggle_repository)
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Togls
|
2
|
+
module RuleManager
|
3
|
+
def self.included(mod)
|
4
|
+
mod.extend(ClassMethods)
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def rule_types(&block)
|
9
|
+
rule_type_registry.expand(&block) if block
|
10
|
+
rule_type_registry
|
11
|
+
end
|
12
|
+
|
13
|
+
def rule_type(type_id)
|
14
|
+
rule_type_registry.get(type_id)
|
15
|
+
end
|
16
|
+
|
17
|
+
def rule(type_id, data = nil, target_type: Togls::TargetTypes::NOT_SET)
|
18
|
+
rule_type(type_id).new(type_id, data, target_type: target_type)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def rule_type_repository
|
24
|
+
if @rule_type_repository.nil?
|
25
|
+
rule_type_repository_drivers = [RuleTypeRepositoryDrivers::InMemoryDriver.new]
|
26
|
+
@rule_type_repository = RuleTypeRepository.new(rule_type_repository_drivers)
|
27
|
+
end
|
28
|
+
@rule_type_repository
|
29
|
+
end
|
30
|
+
|
31
|
+
def rule_type_registry
|
32
|
+
if @rule_type_registry.nil?
|
33
|
+
@rule_type_registry = RuleTypeRegistry.new(rule_type_repository)
|
34
|
+
@rule_type_registry.register(:boolean, Togls::Rules::Boolean)
|
35
|
+
@rule_type_registry.register(:group, Togls::Rules::Group)
|
36
|
+
end
|
37
|
+
@rule_type_registry
|
38
|
+
end
|
39
|
+
|
40
|
+
def rule_repository
|
41
|
+
if @rule_repository.nil?
|
42
|
+
rule_repository_drivers = [
|
43
|
+
Togls::RuleRepositoryDrivers::InMemoryDriver.new,
|
44
|
+
Togls::RuleRepositoryDrivers::EnvOverrideDriver.new
|
45
|
+
]
|
46
|
+
|
47
|
+
@rule_repository = Togls::RuleRepository.new(rule_repository_drivers)
|
48
|
+
end
|
49
|
+
@rule_repository
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -5,7 +5,7 @@ module Togls
|
|
5
5
|
# It does these by interfacing with Rule Repository Drivers which are passed
|
6
6
|
# in during construction as an Array.
|
7
7
|
class RuleRepository
|
8
|
-
def initialize(
|
8
|
+
def initialize(drivers)
|
9
9
|
unless drivers.is_a?(Array)
|
10
10
|
raise Togls::InvalidDriver, 'RuleRepository requires a valid driver'
|
11
11
|
end
|
@@ -13,7 +13,6 @@ module Togls
|
|
13
13
|
raise Togls::MissingDriver, 'RuleRepository requires a driver'
|
14
14
|
end
|
15
15
|
@drivers = drivers
|
16
|
-
@rule_type_registry = rule_type_registry
|
17
16
|
end
|
18
17
|
|
19
18
|
def store(rule)
|
@@ -25,7 +24,7 @@ module Togls
|
|
25
24
|
|
26
25
|
def extract_storage_payload(rule)
|
27
26
|
{
|
28
|
-
'type_id' =>
|
27
|
+
'type_id' => ::Togls.send(:rule_type_registry).get_type_id(rule.class.to_s),
|
29
28
|
'data' => rule.data,
|
30
29
|
'target_type' => rule.target_type.to_s
|
31
30
|
}
|
@@ -69,11 +68,12 @@ module Togls
|
|
69
68
|
|
70
69
|
def reconstitute_rule(rule_data)
|
71
70
|
if rule_data.has_key?('target_type')
|
72
|
-
|
71
|
+
::Togls.rule_type(rule_data['type_id'])\
|
73
72
|
.new(rule_data['type_id'].to_sym, rule_data['data'],
|
74
73
|
target_type: rule_data['target_type'].to_sym)
|
75
74
|
else
|
76
|
-
|
75
|
+
::Togls.rule_type(rule_data['type_id']).new(rule_data['type_id'].to_sym,
|
76
|
+
rule_data['data'])
|
77
77
|
end
|
78
78
|
end
|
79
79
|
end
|
@@ -3,7 +3,7 @@ module Togls
|
|
3
3
|
#
|
4
4
|
# Repository interface for storing and retrieving toggles.
|
5
5
|
class ToggleRepository
|
6
|
-
def initialize(drivers, feature_repository
|
6
|
+
def initialize(drivers, feature_repository)
|
7
7
|
unless drivers.is_a?(Array)
|
8
8
|
raise Togls::InvalidDriver, 'ToggleRepository requires a valid driver'
|
9
9
|
end
|
@@ -12,12 +12,11 @@ module Togls
|
|
12
12
|
end
|
13
13
|
@drivers = drivers
|
14
14
|
@feature_repository = feature_repository
|
15
|
-
@rule_repository = rule_repository
|
16
15
|
end
|
17
16
|
|
18
17
|
def store(toggle)
|
19
18
|
@feature_repository.store(toggle.feature)
|
20
|
-
|
19
|
+
::Togls.send(:rule_repository).store(toggle.rule)
|
21
20
|
payload = extract_storage_payload(toggle)
|
22
21
|
|
23
22
|
@drivers.each do |driver|
|
@@ -43,7 +42,7 @@ module Togls
|
|
43
42
|
end
|
44
43
|
|
45
44
|
begin
|
46
|
-
rule =
|
45
|
+
rule = ::Togls.send(:rule_repository).get(toggle_data['rule_id'])
|
47
46
|
rescue Togls::RepositoryRuleDataInvalid => e
|
48
47
|
return Togls::NullToggle.new
|
49
48
|
end
|
data/lib/togls/version.rb
CHANGED
data/lib/togls.rb
CHANGED
@@ -25,6 +25,7 @@ require 'togls/null_toggle'
|
|
25
25
|
require 'togls/rule'
|
26
26
|
require 'togls/rules'
|
27
27
|
require 'logger'
|
28
|
+
require 'togls/rule_manager'
|
28
29
|
require 'togls/feature_toggle_registry_manager'
|
29
30
|
require 'togls/default_feature_target_type_manager'
|
30
31
|
|
@@ -33,6 +34,7 @@ require 'togls/default_feature_target_type_manager'
|
|
33
34
|
# Togls is the primary interface to the out of the box toggle registry. It is
|
34
35
|
# the namespace the DSL is exposed under.
|
35
36
|
module Togls
|
37
|
+
include RuleManager
|
36
38
|
include FeatureToggleRegistryManager
|
37
39
|
include DefaultFeatureTargetTypeManager
|
38
40
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: togls
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0.0.pre.rc.
|
4
|
+
version: 3.0.0.pre.rc.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brian Miller
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: exe
|
12
12
|
cert_chain: []
|
13
|
-
date: 2016-06-
|
13
|
+
date: 2016-06-27 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: bundler
|
@@ -104,6 +104,7 @@ files:
|
|
104
104
|
- lib/togls/helpers.rb
|
105
105
|
- lib/togls/null_toggle.rb
|
106
106
|
- lib/togls/rule.rb
|
107
|
+
- lib/togls/rule_manager.rb
|
107
108
|
- lib/togls/rule_repository.rb
|
108
109
|
- lib/togls/rule_repository_drivers.rb
|
109
110
|
- lib/togls/rule_repository_drivers/env_override_driver.rb
|