this_feature 0.7.0 → 0.8.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 +24 -24
- data/docs/splitio.md +28 -1
- data/lib/this_feature/adapters/base.rb +2 -2
- data/lib/this_feature/adapters/flipper.rb +2 -2
- data/lib/this_feature/adapters/memory.rb +2 -2
- data/lib/this_feature/adapters/split_io.rb +13 -11
- data/lib/this_feature/configuration.rb +5 -1
- data/lib/this_feature/flag.rb +6 -5
- data/lib/this_feature/version.rb +1 -1
- data/lib/this_feature.rb +8 -4
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4a2e4f072c94b68b9a9e4675ac663f4d6f451d1d7c854e457079d539bd16184e
|
|
4
|
+
data.tar.gz: 6bbda6b3a7257f0a2e1ebd13784c3a78d4eb4ba3340727b99aa9d9df90753ea3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0c0e69e00abb16fc2e781b4fdeb63664af7705280095c1f0a12cb660c5195b886463195e0830c91382474f62cd5c9c0b777aeddb14b494f48040cc2522d238c9
|
|
7
|
+
data.tar.gz: 6b1e05ba21a6409f413ba5b11167f1c17e561a9c2989edde58a1b2f50d1c368c4b76fde8153db4588757d6e4bd93a0f9e36d2fa4874e7190fa8c4347699e9c53
|
data/Gemfile.lock
CHANGED
|
@@ -1,39 +1,38 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
this_feature (0.
|
|
5
|
-
this_feature-adapters-flipper (0.
|
|
4
|
+
this_feature (0.8.0)
|
|
5
|
+
this_feature-adapters-flipper (0.8.0)
|
|
6
6
|
flipper (~> 0.16)
|
|
7
7
|
flipper-active_record (~> 0.16)
|
|
8
8
|
this_feature
|
|
9
|
-
this_feature-adapters-split_io (0.
|
|
9
|
+
this_feature-adapters-split_io (0.8.0)
|
|
10
10
|
splitclient-rb
|
|
11
11
|
this_feature
|
|
12
12
|
|
|
13
13
|
GEM
|
|
14
14
|
remote: https://rubygems.org/
|
|
15
15
|
specs:
|
|
16
|
-
activemodel (
|
|
17
|
-
activesupport (=
|
|
18
|
-
activerecord (
|
|
19
|
-
activemodel (=
|
|
20
|
-
activesupport (=
|
|
21
|
-
activesupport (
|
|
16
|
+
activemodel (7.0.3.1)
|
|
17
|
+
activesupport (= 7.0.3.1)
|
|
18
|
+
activerecord (7.0.3.1)
|
|
19
|
+
activemodel (= 7.0.3.1)
|
|
20
|
+
activesupport (= 7.0.3.1)
|
|
21
|
+
activesupport (7.0.3.1)
|
|
22
22
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
23
23
|
i18n (>= 1.6, < 2)
|
|
24
24
|
minitest (>= 5.1)
|
|
25
25
|
tzinfo (~> 2.0)
|
|
26
|
-
zeitwerk (~> 2.3)
|
|
27
26
|
byebug (11.1.2)
|
|
28
27
|
coderay (1.1.2)
|
|
29
|
-
concurrent-ruby (1.1.
|
|
28
|
+
concurrent-ruby (1.1.10)
|
|
30
29
|
connection_pool (2.2.5)
|
|
31
30
|
database_cleaner (1.8.4)
|
|
32
31
|
database_cleaner-active_record (1.8.0)
|
|
33
32
|
activerecord
|
|
34
33
|
database_cleaner (~> 1.8.0)
|
|
35
34
|
diff-lcs (1.3)
|
|
36
|
-
faraday (1.
|
|
35
|
+
faraday (1.7.0)
|
|
37
36
|
faraday-em_http (~> 1.0)
|
|
38
37
|
faraday-em_synchrony (~> 1.0)
|
|
39
38
|
faraday-excon (~> 1.1)
|
|
@@ -41,6 +40,7 @@ GEM
|
|
|
41
40
|
faraday-net_http (~> 1.0)
|
|
42
41
|
faraday-net_http_persistent (~> 1.1)
|
|
43
42
|
faraday-patron (~> 1.0)
|
|
43
|
+
faraday-rack (~> 1.0)
|
|
44
44
|
multipart-post (>= 1.2, < 3)
|
|
45
45
|
ruby2_keywords (>= 0.0.4)
|
|
46
46
|
faraday-em_http (1.0.0)
|
|
@@ -48,21 +48,22 @@ GEM
|
|
|
48
48
|
faraday-excon (1.1.0)
|
|
49
49
|
faraday-httpclient (1.0.1)
|
|
50
50
|
faraday-net_http (1.0.1)
|
|
51
|
-
faraday-net_http_persistent (1.
|
|
51
|
+
faraday-net_http_persistent (1.2.0)
|
|
52
52
|
faraday-patron (1.0.0)
|
|
53
|
-
|
|
54
|
-
flipper
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
faraday-rack (1.0.0)
|
|
54
|
+
flipper (0.25.0)
|
|
55
|
+
flipper-active_record (0.25.0)
|
|
56
|
+
activerecord (>= 4.2, < 8)
|
|
57
|
+
flipper (~> 0.25.0)
|
|
57
58
|
gem-release (2.2.1)
|
|
58
59
|
hitimes (1.3.1)
|
|
59
|
-
i18n (1.
|
|
60
|
+
i18n (1.11.0)
|
|
60
61
|
concurrent-ruby (~> 1.0)
|
|
61
62
|
json (2.5.1)
|
|
62
63
|
jwt (2.2.3)
|
|
63
64
|
lru_redux (1.1.0)
|
|
64
65
|
method_source (1.0.0)
|
|
65
|
-
minitest (5.
|
|
66
|
+
minitest (5.16.2)
|
|
66
67
|
multipart-post (2.1.1)
|
|
67
68
|
net-http-persistent (4.0.1)
|
|
68
69
|
connection_pool (~> 2.2)
|
|
@@ -73,7 +74,7 @@ GEM
|
|
|
73
74
|
byebug (~> 11.0)
|
|
74
75
|
pry (~> 0.13.0)
|
|
75
76
|
rake (13.0.1)
|
|
76
|
-
redis (4.
|
|
77
|
+
redis (4.4.0)
|
|
77
78
|
rspec (3.9.0)
|
|
78
79
|
rspec-core (~> 3.9.0)
|
|
79
80
|
rspec-expectations (~> 3.9.0)
|
|
@@ -87,10 +88,10 @@ GEM
|
|
|
87
88
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
88
89
|
rspec-support (~> 3.9.0)
|
|
89
90
|
rspec-support (3.9.2)
|
|
90
|
-
ruby2_keywords (0.0.
|
|
91
|
+
ruby2_keywords (0.0.5)
|
|
91
92
|
socketry (0.5.1)
|
|
92
93
|
hitimes (~> 1.2)
|
|
93
|
-
splitclient-rb (7.
|
|
94
|
+
splitclient-rb (7.3.1)
|
|
94
95
|
concurrent-ruby (~> 1.0)
|
|
95
96
|
faraday (>= 0.8)
|
|
96
97
|
json (>= 1.8)
|
|
@@ -104,7 +105,6 @@ GEM
|
|
|
104
105
|
thread_safe (0.3.6)
|
|
105
106
|
tzinfo (2.0.4)
|
|
106
107
|
concurrent-ruby (~> 1.0)
|
|
107
|
-
zeitwerk (2.4.2)
|
|
108
108
|
|
|
109
109
|
PLATFORMS
|
|
110
110
|
ruby
|
|
@@ -122,4 +122,4 @@ DEPENDENCIES
|
|
|
122
122
|
this_feature-adapters-split_io!
|
|
123
123
|
|
|
124
124
|
BUNDLED WITH
|
|
125
|
-
2.
|
|
125
|
+
2.3.21
|
data/docs/splitio.md
CHANGED
|
@@ -32,4 +32,31 @@ The SplitIo adapter supports the public API of `ThisFeature`.
|
|
|
32
32
|
|
|
33
33
|
Both `context` and `data` are supported.
|
|
34
34
|
|
|
35
|
-
`control` is a native Split feature, so we perform a query to Split to get this info.
|
|
35
|
+
`control` is a native Split feature, so we perform a query to Split to get this info.
|
|
36
|
+
|
|
37
|
+
We've also added `record`, which is a helper to easily and consistently add
|
|
38
|
+
attributes to the `data` hash. To take advantage of this, the application must
|
|
39
|
+
set a `base_data_lambda` in the config. An example—
|
|
40
|
+
```ruby
|
|
41
|
+
ThisFeature.configure do |config|
|
|
42
|
+
config.base_data_lambda = -> (record) do
|
|
43
|
+
case record
|
|
44
|
+
when Org
|
|
45
|
+
{
|
|
46
|
+
org_id: record.id,
|
|
47
|
+
org_name: record.name
|
|
48
|
+
}
|
|
49
|
+
when User
|
|
50
|
+
{
|
|
51
|
+
org_id: record.org.id,
|
|
52
|
+
org_name: record.org.name,
|
|
53
|
+
user_email: record.email,
|
|
54
|
+
user_id: record.id,
|
|
55
|
+
user_name: record.name,
|
|
56
|
+
}
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
```
|
|
61
|
+
Then `ThisFeature.flag("my-flag", record: user).on?` will automatically include
|
|
62
|
+
org_id, org_name, user_email, user_id, and user_name in the data attributes.
|
|
@@ -5,11 +5,11 @@ class ThisFeature
|
|
|
5
5
|
raise UnimplementedError.new(self, __method__)
|
|
6
6
|
end
|
|
7
7
|
|
|
8
|
-
def on?(flag_name, context: nil, data: {})
|
|
8
|
+
def on?(flag_name, context: nil, data: {}, record: nil)
|
|
9
9
|
raise UnimplementedError.new(self, __method__)
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
def off?(flag_name, context: nil, data: {})
|
|
12
|
+
def off?(flag_name, context: nil, data: {}, record: nil)
|
|
13
13
|
raise UnimplementedError.new(self, __method__)
|
|
14
14
|
end
|
|
15
15
|
|
|
@@ -18,11 +18,11 @@ class ThisFeature
|
|
|
18
18
|
!present?(flag_name)
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
def on?(flag_name, context: nil, data: {})
|
|
21
|
+
def on?(flag_name, context: nil, data: {}, record: nil)
|
|
22
22
|
client[flag_name].enabled?(*[context].compact)
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
-
def off?(flag_name, context: nil, data: {})
|
|
25
|
+
def off?(flag_name, context: nil, data: {}, record: nil)
|
|
26
26
|
!on?(flag_name, context: context)
|
|
27
27
|
end
|
|
28
28
|
|
|
@@ -14,7 +14,7 @@ class ThisFeature
|
|
|
14
14
|
!storage[flag_name].nil?
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
def on?(flag_name, context: nil, data: {})
|
|
17
|
+
def on?(flag_name, context: nil, data: {}, record: nil)
|
|
18
18
|
return false unless present?(flag_name)
|
|
19
19
|
|
|
20
20
|
flag_data = storage[flag_name]
|
|
@@ -27,7 +27,7 @@ class ThisFeature
|
|
|
27
27
|
!!flag_data[:contexts][context_key(context)]
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
-
def off?(flag_name, context: nil, data: {})
|
|
30
|
+
def off?(flag_name, context: nil, data: {}, record: nil)
|
|
31
31
|
!on?(flag_name, context: context, data: data)
|
|
32
32
|
end
|
|
33
33
|
|
|
@@ -3,8 +3,9 @@ require 'splitclient-rb'
|
|
|
3
3
|
class ThisFeature
|
|
4
4
|
module Adapters
|
|
5
5
|
class SplitIo < Base
|
|
6
|
-
#
|
|
7
|
-
|
|
6
|
+
# Used as the context key when none is given. This arg is required by
|
|
7
|
+
# Split, but it's nice not to have to pass it when the context is empty.
|
|
8
|
+
EMPTY_CONTEXT = 'undefined_key'
|
|
8
9
|
|
|
9
10
|
def initialize(client: nil, context_key_method: nil)
|
|
10
11
|
@client = client || default_split_client
|
|
@@ -17,28 +18,29 @@ class ThisFeature
|
|
|
17
18
|
!control?(flag_name)
|
|
18
19
|
end
|
|
19
20
|
|
|
20
|
-
def control?(flag_name, context:
|
|
21
|
-
treatment(flag_name, context: context, data: data).include?('control')
|
|
21
|
+
def control?(flag_name, context: EMPTY_CONTEXT, data: {}, record: nil)
|
|
22
|
+
treatment(flag_name, context: context, data: data, record: record).include?('control')
|
|
22
23
|
end
|
|
23
24
|
|
|
24
|
-
def on?(flag_name, context:
|
|
25
|
-
treatment(flag_name, context: context, data: data).eql?('on')
|
|
25
|
+
def on?(flag_name, context: EMPTY_CONTEXT, data: {}, record: nil)
|
|
26
|
+
treatment(flag_name, context: context, data: data, record: record).eql?('on')
|
|
26
27
|
end
|
|
27
28
|
|
|
28
|
-
def off?(flag_name, context:
|
|
29
|
-
treatment(flag_name, context: context, data: data).eql?('off')
|
|
29
|
+
def off?(flag_name, context: EMPTY_CONTEXT, data: {}, record: nil)
|
|
30
|
+
treatment(flag_name, context: context, data: data, record: record).eql?('off')
|
|
30
31
|
end
|
|
31
32
|
|
|
32
33
|
private
|
|
33
34
|
|
|
34
35
|
attr_reader :client, :context_key_method
|
|
35
36
|
|
|
36
|
-
def treatment(flag_name, context:
|
|
37
|
-
|
|
37
|
+
def treatment(flag_name, context: EMPTY_CONTEXT, data: {}, record: nil)
|
|
38
|
+
base_data = record ? ThisFeature.base_data_lambda.call(record) : {}
|
|
39
|
+
client.get_treatment(context_key(context), flag_name, base_data.merge(data))
|
|
38
40
|
end
|
|
39
41
|
|
|
40
42
|
def context_key(context)
|
|
41
|
-
return
|
|
43
|
+
return EMPTY_CONTEXT if context.nil? || context.eql?(EMPTY_CONTEXT)
|
|
42
44
|
return context.send(context_key_method) unless context_key_method.nil?
|
|
43
45
|
return context.to_s if context.respond_to?(:to_s)
|
|
44
46
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
class ThisFeature
|
|
2
2
|
class Configuration
|
|
3
|
-
attr_writer :adapters, :default_adapter, :test_adapter
|
|
3
|
+
attr_writer :adapters, :default_adapter, :test_adapter, :base_data_lambda
|
|
4
4
|
|
|
5
5
|
def init
|
|
6
6
|
validate_adapters!
|
|
@@ -25,5 +25,9 @@ class ThisFeature
|
|
|
25
25
|
def test_adapter
|
|
26
26
|
@test_adapter ||= Adapters::Memory.new
|
|
27
27
|
end
|
|
28
|
+
|
|
29
|
+
def base_data_lambda
|
|
30
|
+
@base_data_lambda ||= -> (record) { {} }
|
|
31
|
+
end
|
|
28
32
|
end
|
|
29
33
|
end
|
data/lib/this_feature/flag.rb
CHANGED
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
class ThisFeature
|
|
2
2
|
class Flag
|
|
3
|
-
attr_reader :flag_name, :context, :data, :adapter
|
|
3
|
+
attr_reader :flag_name, :context, :data, :adapter, :record
|
|
4
4
|
|
|
5
|
-
def initialize(flag_name, adapter:, context: nil, data: {})
|
|
5
|
+
def initialize(flag_name, adapter:, context: nil, data: {}, record: nil)
|
|
6
6
|
@flag_name = flag_name
|
|
7
7
|
@adapter = adapter
|
|
8
8
|
@context = context
|
|
9
9
|
@data = data
|
|
10
|
+
@record = record
|
|
10
11
|
end
|
|
11
12
|
|
|
12
13
|
def on?
|
|
13
|
-
adapter.on?(flag_name, context: context, data: data)
|
|
14
|
+
adapter.on?(flag_name, context: context, data: data, record: record)
|
|
14
15
|
end
|
|
15
16
|
|
|
16
17
|
def off?
|
|
17
|
-
adapter.off?(flag_name, context: context, data: data)
|
|
18
|
+
adapter.off?(flag_name, context: context, data: data, record: record)
|
|
18
19
|
end
|
|
19
20
|
|
|
20
21
|
def control?
|
|
21
|
-
adapter.control?(flag_name, context: context, data: data)
|
|
22
|
+
adapter.control?(flag_name, context: context, data: data, record: record)
|
|
22
23
|
end
|
|
23
24
|
end
|
|
24
25
|
end
|
data/lib/this_feature/version.rb
CHANGED
data/lib/this_feature.rb
CHANGED
|
@@ -5,13 +5,13 @@ require 'this_feature/configuration'
|
|
|
5
5
|
require 'this_feature/flag'
|
|
6
6
|
|
|
7
7
|
class ThisFeature
|
|
8
|
-
def self.flag(flag_name, context: nil, data: {})
|
|
9
|
-
adapter = adapter_for(flag_name
|
|
8
|
+
def self.flag(flag_name, context: nil, data: {}, record: nil)
|
|
9
|
+
adapter = adapter_for(flag_name)
|
|
10
10
|
|
|
11
|
-
Flag.new(flag_name, adapter: adapter, context: context, data: data)
|
|
11
|
+
Flag.new(flag_name, adapter: adapter, context: context, data: data, record: record)
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
def self.adapter_for(flag_name
|
|
14
|
+
def self.adapter_for(flag_name)
|
|
15
15
|
matching_adapter = adapters.find do |adapter|
|
|
16
16
|
adapter.present?(flag_name)
|
|
17
17
|
end
|
|
@@ -38,4 +38,8 @@ class ThisFeature
|
|
|
38
38
|
def self.test_adapter
|
|
39
39
|
configuration.test_adapter
|
|
40
40
|
end
|
|
41
|
+
|
|
42
|
+
def self.base_data_lambda
|
|
43
|
+
configuration.base_data_lambda
|
|
44
|
+
end
|
|
41
45
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: this_feature
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.8.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Max Pleaner
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2023-01-04 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|