this_feature 0.9.0 → 0.10.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/Gemfile.lock +3 -3
- data/README.md +4 -0
- data/docs/memory.md +48 -0
- data/lib/this_feature/adapters/memory.rb +20 -0
- data/lib/this_feature/adapters/split_io.rb +13 -0
- data/lib/this_feature/flag.rb +8 -0
- data/lib/this_feature/version.rb +1 -1
- data/this_feature-adapters-flipper.gemspec +4 -5
- data/this_feature-adapters-split_io.gemspec +4 -5
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7a1fb53b4ceabfd85df7c059b02331d419259b23d7f0de2d90c942528bab1bbc
|
4
|
+
data.tar.gz: 81f8b34041e14e8d02c455c9c427c760b5d02ddf50531f016867f91bb7668368
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8eb7586c9d9b39cabe35d29257e79352f4eb807104f685fd23286717a6b358435c724bc194997b01bd8270d13de743374f763c6e32e4be355fa1db3c46caceb3
|
7
|
+
data.tar.gz: 3b0f23e8392bb6eb1eb52bf3858fb064aad0e59d5c5ef535e15ccb95acf88a974c64ae2ad32d0ee925e37b34ff55bf6b499e459593c656c7a01c5fee55712498
|
data/Gemfile.lock
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
this_feature (0.
|
5
|
-
this_feature-adapters-flipper (0.
|
4
|
+
this_feature (0.10.0)
|
5
|
+
this_feature-adapters-flipper (0.10.0)
|
6
6
|
flipper
|
7
7
|
flipper-active_record
|
8
8
|
this_feature
|
9
|
-
this_feature-adapters-split_io (0.
|
9
|
+
this_feature-adapters-split_io (0.10.0)
|
10
10
|
splitclient-rb
|
11
11
|
this_feature
|
12
12
|
|
data/README.md
CHANGED
@@ -98,6 +98,10 @@ bundle install && bundle exec rspec
|
|
98
98
|
|
99
99
|
To write a new adapter, check the [Guide](./docs/writing_an_adapter.md).
|
100
100
|
|
101
|
+
## Deployment
|
102
|
+
|
103
|
+
If you are working at Hover, see [this confluence doc](https://hoverinc.atlassian.net/wiki/spaces/EN/pages/3149266988/deploying+this+feature+gem)
|
104
|
+
|
101
105
|
## License
|
102
106
|
|
103
107
|
ThisFeature is released under the [MIT License](https://choosealicense.com/licenses/mit).
|
data/docs/memory.md
CHANGED
@@ -12,6 +12,13 @@ Under the hood, the memory adapter stores data in a dictionary like so:
|
|
12
12
|
User1: true,
|
13
13
|
User2: false
|
14
14
|
}
|
15
|
+
},
|
16
|
+
some_flag_name_with_treatments: {
|
17
|
+
treatment_contexts: {
|
18
|
+
User1: 'treatment_name_1',
|
19
|
+
User2: 'treatment_name_2',
|
20
|
+
User3: 'treatment_name_3'
|
21
|
+
}
|
15
22
|
}
|
16
23
|
}
|
17
24
|
```
|
@@ -79,6 +86,47 @@ ThisFeature.test_adapter.on!(:flag_name, context: user) # with context
|
|
79
86
|
ThisFeature.test_adapter.off!(:flag_name) # without context
|
80
87
|
```
|
81
88
|
|
89
|
+
### **#enable_treatment!**
|
90
|
+
|
91
|
+
This method is useful when you need to enable a feature flag with a treatment (or multiple treatments), and not just `"on"` and `"off"`.
|
92
|
+
|
93
|
+
Usage example of these:
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
# If you have configured the in-memory adapter as the default
|
97
|
+
ThisFeature.test_adapter.enable_treatment!(:flag_name, treatment: 'treatment_name', context: user)
|
98
|
+
```
|
99
|
+
#### This method requires 3 arguments:
|
100
|
+
1. `flag_name`: String or Symbol (not a named argument)
|
101
|
+
2. `treatment`: String
|
102
|
+
3. `context`: User or Org object
|
103
|
+
|
104
|
+
Per flag name, there can only be one treatment per `context_key` (the ID of object that is provided as `context`). So multiple calls with the same `context`, but different treatment names, will be overwritten.
|
105
|
+
|
106
|
+
```ruby
|
107
|
+
ThisFeature.test_adapter.enable_treatment!('flag_a', treatment: 'treatment_1', context: user1)
|
108
|
+
ThisFeature.test_adapter.storage # => { 'flag_a' => { :treatment_contexts => { 'User1': 'treatment_1' } } }
|
109
|
+
|
110
|
+
ThisFeature.test_adapter.enable_treatment!(:flag_a, treatment: 'treatment_2', context: user1)
|
111
|
+
ThisFeature.test_adapter.storage # => { 'flag_a' => { :treatment_contexts => { 'User1': 'treatment_2' } } }
|
112
|
+
```
|
113
|
+
|
114
|
+
### **#treatment_value**
|
115
|
+
|
116
|
+
You can retrieve the flag's treatment name for a specific context.
|
117
|
+
|
118
|
+
Usage example of these:
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
# If you have configured the in-memory adapter as the default
|
122
|
+
ThisFeature.test_adapter.treatment_value(:flag_name, context: user)
|
123
|
+
```
|
124
|
+
|
125
|
+
#### This method requires 2 arguments:
|
126
|
+
1. `flag_name`: String or Symbol (not a named argument)
|
127
|
+
2. `context`: User or Org object
|
128
|
+
|
129
|
+
When the Memory storage does not contain the given flag_name or if there is no provided `context`, `"control"` is returned. This is meant to mimic what SplitIO would return in the case of no configured treatment for the given `context`.
|
82
130
|
### **#clear**
|
83
131
|
|
84
132
|
Since the memory adapter stores flags in memory, it won't automatically get cleaned up in your tests. You can use this method to reset the memory adapter state.
|
@@ -34,6 +34,26 @@ class ThisFeature
|
|
34
34
|
!present?(flag_name)
|
35
35
|
end
|
36
36
|
|
37
|
+
def treatment_value(flag_name, context: nil, data: {}, record: nil)
|
38
|
+
return 'control' if !present?(flag_name) || context.nil?
|
39
|
+
|
40
|
+
flag_data = storage[flag_name][:treatment_contexts]
|
41
|
+
context_registered = flag_data&.key?(context_key(context))
|
42
|
+
|
43
|
+
return 'control' if !flag_data || !context_registered
|
44
|
+
|
45
|
+
flag_data ||= {}
|
46
|
+
flag_data[context_key(context)]
|
47
|
+
end
|
48
|
+
|
49
|
+
def enable_treatment!(flag_name, treatment: nil, context: nil)
|
50
|
+
return false if treatment.nil? || flag_name.nil? || context.nil?
|
51
|
+
|
52
|
+
storage[flag_name] ||= {}
|
53
|
+
storage[flag_name][:treatment_contexts] ||= {}
|
54
|
+
storage[flag_name][:treatment_contexts][context_key(context)] = treatment
|
55
|
+
end
|
56
|
+
|
37
57
|
def on!(flag_name, context: nil, data: {})
|
38
58
|
storage[flag_name] ||= {}
|
39
59
|
|
@@ -30,6 +30,14 @@ class ThisFeature
|
|
30
30
|
treatment(flag_name, context: context, data: data, record: record).eql?('off')
|
31
31
|
end
|
32
32
|
|
33
|
+
def treatment_value(flag_name, context: EMPTY_CONTEXT, data: {}, record: nil)
|
34
|
+
treatment_with_config(flag_name, context: context, data: data, record: record)[:treatment]
|
35
|
+
end
|
36
|
+
|
37
|
+
def treatment_config(flag_name, context: EMPTY_CONTEXT, data: {}, record: nil)
|
38
|
+
treatment_with_config(flag_name, context: context, data: data, record: record)[:config]
|
39
|
+
end
|
40
|
+
|
33
41
|
private
|
34
42
|
|
35
43
|
attr_reader :client, :context_key_method
|
@@ -39,6 +47,11 @@ class ThisFeature
|
|
39
47
|
client.get_treatment(context_key(context), flag_name, base_data.merge(data))
|
40
48
|
end
|
41
49
|
|
50
|
+
def treatment_with_config(flag_name, context: EMPTY_CONTEXT, data: {}, record: nil)
|
51
|
+
base_data = record ? ThisFeature.base_data_lambda.call(record) : {}
|
52
|
+
client.get_treatment_with_config(context_key(context), flag_name, base_data.merge(data))
|
53
|
+
end
|
54
|
+
|
42
55
|
def context_key(context)
|
43
56
|
return EMPTY_CONTEXT if context.nil? || context.eql?(EMPTY_CONTEXT)
|
44
57
|
return context.send(context_key_method) unless context_key_method.nil?
|
data/lib/this_feature/flag.rb
CHANGED
@@ -21,5 +21,13 @@ class ThisFeature
|
|
21
21
|
def control?
|
22
22
|
adapter.control?(flag_name, context: context, data: data, record: record)
|
23
23
|
end
|
24
|
+
|
25
|
+
def treatment_value
|
26
|
+
adapter.treatment_value(flag_name, context: context, data: data, record: record)
|
27
|
+
end
|
28
|
+
|
29
|
+
def treatment_config
|
30
|
+
adapter.treatment_config(flag_name, context: context, data: data, record: record)
|
31
|
+
end
|
24
32
|
end
|
25
33
|
end
|
data/lib/this_feature/version.rb
CHANGED
@@ -10,17 +10,16 @@ Gem::Specification.new do |spec|
|
|
10
10
|
|
11
11
|
spec.authors = ['Max Pleaner', 'Matt Fong']
|
12
12
|
spec.email = ['maxpleaner@gmail.com', 'matthewjf@gmail.com']
|
13
|
-
spec.homepage = 'http://hover.to'
|
14
|
-
|
15
|
-
spec.metadata['homepage_uri'] = spec.homepage
|
16
|
-
spec.metadata['source_code_uri'] = spec.homepage
|
17
|
-
spec.metadata['rubygems_mfa_required'] = 'true'
|
18
13
|
|
19
14
|
spec.licenses = ['MIT']
|
20
15
|
spec.summary = 'A ThisFeature adapter to Flipper'
|
21
16
|
spec.description = ''
|
22
17
|
spec.homepage = 'https://github.com/hoverinc/this_feature'
|
23
18
|
|
19
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
20
|
+
spec.metadata['source_code_uri'] = spec.homepage
|
21
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
22
|
+
|
24
23
|
spec.files = Dir.glob('{bin/*,lib/**/*,[A-Z]*}')
|
25
24
|
spec.platform = Gem::Platform::RUBY
|
26
25
|
spec.require_paths = ['lib']
|
@@ -10,17 +10,16 @@ Gem::Specification.new do |spec|
|
|
10
10
|
|
11
11
|
spec.authors = ['Max Pleaner', 'Matt Fong']
|
12
12
|
spec.email = ['maxpleaner@gmail.com', 'matthewjf@gmail.com']
|
13
|
-
spec.homepage = 'http://hover.to'
|
14
|
-
|
15
|
-
spec.metadata['homepage_uri'] = spec.homepage
|
16
|
-
spec.metadata['source_code_uri'] = spec.homepage
|
17
|
-
spec.metadata['rubygems_mfa_required'] = 'true'
|
18
13
|
|
19
14
|
spec.licenses = ['MIT']
|
20
15
|
spec.summary = 'A ThisFeature adapter to Split.io'
|
21
16
|
spec.description = ''
|
22
17
|
spec.homepage = 'https://github.com/hoverinc/this_feature'
|
23
18
|
|
19
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
20
|
+
spec.metadata['source_code_uri'] = spec.homepage
|
21
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
22
|
+
|
24
23
|
spec.files = Dir.glob('{bin/*,lib/**/*,[A-Z]*}')
|
25
24
|
spec.platform = Gem::Platform::RUBY
|
26
25
|
spec.require_paths = ['lib']
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: this_feature
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Max Pleaner
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: exe
|
13
13
|
cert_chain: []
|
14
|
-
date: 2023-
|
14
|
+
date: 2023-10-16 00:00:00.000000000 Z
|
15
15
|
dependencies: []
|
16
16
|
description: ''
|
17
17
|
email:
|
@@ -78,7 +78,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
78
78
|
- !ruby/object:Gem::Version
|
79
79
|
version: '0'
|
80
80
|
requirements: []
|
81
|
-
rubygems_version: 3.4.
|
81
|
+
rubygems_version: 3.4.10
|
82
82
|
signing_key:
|
83
83
|
specification_version: 4
|
84
84
|
summary: A common interface to interact with many feature flag providers
|