simple_feature_flags 1.4.0 → 1.4.1
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 +2 -2
- data/Gemfile.lock +32 -20
- data/README.md +30 -0
- data/lib/simple_feature_flags/base_storage.rb +15 -5
- data/lib/simple_feature_flags/cli/command/generate.rb +15 -21
- data/lib/simple_feature_flags/cli/options.rb +8 -8
- data/lib/simple_feature_flags/cli/runner.rb +3 -3
- data/lib/simple_feature_flags/configuration.rb +2 -2
- data/lib/simple_feature_flags/ram_storage.rb +91 -173
- data/lib/simple_feature_flags/redis_storage.rb +84 -166
- data/lib/simple_feature_flags/test_ram_storage.rb +2 -1
- data/lib/simple_feature_flags/version.rb +2 -1
- data/lib/simple_feature_flags.rb +4 -14
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a31152f17215cd2905c721f27217aaa187c006345a5c811ca6194ae36fabef89
|
4
|
+
data.tar.gz: 9df276339edd478dc86e0ce590518c21ebc115f63899fe493ad328d11180ae5d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8b02dde3a77725c376a0375d8c291e308ee5ce8e7b885e2e051a08e8205eb8407b64e460e43ee6a404a504dd9f9bf1248f387a6764870ec444c3c44f0b423f71
|
7
|
+
data.tar.gz: f3f1cdecad7872b6c10c3a1e086f773844e04bf3869fc07d6661fef81dcf33fdb78f2d731318b3f6410cc6ca039fb10625bedb4ffc854f865b0ccf3cfe98f1b6
|
data/Gemfile
CHANGED
@@ -12,5 +12,5 @@ gem 'redis', '~> 5.3' # redis client
|
|
12
12
|
gem 'redis-namespace', '~> 1.11' # namespaces for redis
|
13
13
|
gem 'rubocop-espago', '~> 1.1' # ruby linter
|
14
14
|
gem 'rubocop-sorbet', '~> 0.10' # rubocop for sorbet
|
15
|
-
gem 'sorbet', '
|
16
|
-
gem 'tapioca', '
|
15
|
+
gem 'sorbet', '~> 0.5' # static typechecker
|
16
|
+
gem 'tapioca', '~> 0.17' # RBI generator for sorbet
|
data/Gemfile.lock
CHANGED
@@ -1,32 +1,37 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
simple_feature_flags (1.4.
|
4
|
+
simple_feature_flags (1.4.1)
|
5
5
|
sorbet-runtime (> 0.5)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
10
|
ast (2.4.3)
|
11
|
+
benchmark (0.4.1)
|
11
12
|
byebug (11.1.3)
|
12
13
|
connection_pool (2.4.1)
|
13
|
-
erubi (1.13.
|
14
|
+
erubi (1.13.1)
|
14
15
|
json (2.10.2)
|
15
16
|
language_server-protocol (3.17.0.4)
|
16
17
|
lint_roller (1.1.0)
|
18
|
+
logger (1.7.0)
|
17
19
|
minitest (5.25.1)
|
18
20
|
netrc (0.11.0)
|
19
21
|
parallel (1.27.0)
|
20
22
|
parser (3.3.8.0)
|
21
23
|
ast (~> 2.4.1)
|
22
24
|
racc
|
23
|
-
prism (1.
|
25
|
+
prism (1.4.0)
|
24
26
|
racc (1.8.1)
|
25
27
|
rainbow (3.1.1)
|
26
28
|
rake (13.2.1)
|
27
|
-
rbi (0.
|
29
|
+
rbi (0.3.6)
|
28
30
|
prism (~> 1.0)
|
29
|
-
|
31
|
+
rbs (>= 3.4.4)
|
32
|
+
rbs (4.0.0.dev.4)
|
33
|
+
logger
|
34
|
+
prism (>= 1.3.0)
|
30
35
|
redis (5.3.0)
|
31
36
|
redis-client (>= 0.22.0)
|
32
37
|
redis-client (0.22.2)
|
@@ -34,6 +39,8 @@ GEM
|
|
34
39
|
redis-namespace (1.11.0)
|
35
40
|
redis (>= 4)
|
36
41
|
regexp_parser (2.10.0)
|
42
|
+
require-hooks (0.2.2)
|
43
|
+
rexml (3.4.1)
|
37
44
|
rubocop (1.74.0)
|
38
45
|
json (~> 2.3)
|
39
46
|
language_server-protocol (~> 3.17.0.2)
|
@@ -52,27 +59,32 @@ GEM
|
|
52
59
|
rubocop-sorbet (0.10.0)
|
53
60
|
rubocop (>= 1)
|
54
61
|
ruby-progressbar (1.13.0)
|
55
|
-
sorbet (0.5.
|
56
|
-
sorbet-static (= 0.5.
|
57
|
-
sorbet-runtime (0.5.
|
58
|
-
sorbet-static (0.5.
|
59
|
-
sorbet-static (0.5.
|
60
|
-
sorbet-static (0.5.
|
61
|
-
sorbet-static-and-runtime (0.5.
|
62
|
-
sorbet (= 0.5.
|
63
|
-
sorbet-runtime (= 0.5.
|
64
|
-
spoom (1.
|
62
|
+
sorbet (0.5.12210)
|
63
|
+
sorbet-static (= 0.5.12210)
|
64
|
+
sorbet-runtime (0.5.12210)
|
65
|
+
sorbet-static (0.5.12210-aarch64-linux)
|
66
|
+
sorbet-static (0.5.12210-universal-darwin)
|
67
|
+
sorbet-static (0.5.12210-x86_64-linux)
|
68
|
+
sorbet-static-and-runtime (0.5.12210)
|
69
|
+
sorbet (= 0.5.12210)
|
70
|
+
sorbet-runtime (= 0.5.12210)
|
71
|
+
spoom (1.7.4)
|
65
72
|
erubi (>= 1.10.0)
|
66
73
|
prism (>= 0.28.0)
|
74
|
+
rbi (>= 0.3.3)
|
75
|
+
rbs (>= 4.0.0.dev.4)
|
76
|
+
rexml (>= 3.2.6)
|
67
77
|
sorbet-static-and-runtime (>= 0.5.10187)
|
68
78
|
thor (>= 0.19.2)
|
69
|
-
tapioca (0.
|
79
|
+
tapioca (0.17.5)
|
80
|
+
benchmark
|
70
81
|
bundler (>= 2.2.25)
|
71
82
|
netrc (>= 0.11.0)
|
72
83
|
parallel (>= 1.21.0)
|
73
|
-
rbi (
|
84
|
+
rbi (>= 0.3.1)
|
85
|
+
require-hooks (>= 0.2.2)
|
74
86
|
sorbet-static-and-runtime (>= 0.5.11087)
|
75
|
-
spoom (>= 1.
|
87
|
+
spoom (>= 1.7.0)
|
76
88
|
thor (>= 1.2.0)
|
77
89
|
yard-sorbet
|
78
90
|
thor (1.3.2)
|
@@ -98,8 +110,8 @@ DEPENDENCIES
|
|
98
110
|
rubocop-espago (~> 1.1)
|
99
111
|
rubocop-sorbet (~> 0.10)
|
100
112
|
simple_feature_flags!
|
101
|
-
sorbet (
|
102
|
-
tapioca (
|
113
|
+
sorbet (~> 0.5)
|
114
|
+
tapioca (~> 0.17)
|
103
115
|
|
104
116
|
BUNDLED WITH
|
105
117
|
2.6.8
|
data/README.md
CHANGED
@@ -151,6 +151,21 @@ FEATURE_FLAGS.inactive_globally?(:feature_name) #=> false
|
|
151
151
|
FEATURE_FLAGS.inactive_partially?(:feature_name) #=> true
|
152
152
|
```
|
153
153
|
|
154
|
+
#### Activate a feature in a block
|
155
|
+
|
156
|
+
Activates a feature for the code in the given block
|
157
|
+
then restores the original state of the feature.
|
158
|
+
|
159
|
+
```ruby
|
160
|
+
FEATURE_FLAGS.active?(:feature_name) #=> false
|
161
|
+
|
162
|
+
FEATURE_FLAGS.do_activate(:feature_name) do
|
163
|
+
FEATURE_FLAGS.active?(:feature_name) #=> true
|
164
|
+
end
|
165
|
+
|
166
|
+
FEATURE_FLAGS.active?(:feature_name) #=> false
|
167
|
+
```
|
168
|
+
|
154
169
|
#### Deactivate a feature
|
155
170
|
|
156
171
|
Deactivates a feature in the global scope
|
@@ -165,6 +180,21 @@ FEATURE_FLAGS.active?(:feature_name) #=> false
|
|
165
180
|
FEATURE_FLAGS.inactive?(:feature_name) #=> true
|
166
181
|
```
|
167
182
|
|
183
|
+
#### Deactivate a feature in a block
|
184
|
+
|
185
|
+
Activates a feature for the code in the given block
|
186
|
+
then restores the original state of the feature.
|
187
|
+
|
188
|
+
```ruby
|
189
|
+
FEATURE_FLAGS.active?(:feature_name) #=> true
|
190
|
+
|
191
|
+
FEATURE_FLAGS.do_deactivate(:feature_name) do
|
192
|
+
FEATURE_FLAGS.active?(:feature_name) #=> false
|
193
|
+
end
|
194
|
+
|
195
|
+
FEATURE_FLAGS.active?(:feature_name) #=> true
|
196
|
+
```
|
197
|
+
|
168
198
|
#### Activate a feature for a particular record/object
|
169
199
|
|
170
200
|
```ruby
|
@@ -5,11 +5,9 @@ require 'yaml'
|
|
5
5
|
|
6
6
|
module SimpleFeatureFlags
|
7
7
|
# Abstract class for all storage adapters.
|
8
|
+
# @abstract
|
8
9
|
class BaseStorage
|
9
10
|
extend T::Sig
|
10
|
-
extend T::Helpers
|
11
|
-
|
12
|
-
abstract!
|
13
11
|
|
14
12
|
# Path to the file with feature flags
|
15
13
|
sig { abstract.returns(String) }
|
@@ -245,6 +243,18 @@ module SimpleFeatureFlags
|
|
245
243
|
sig { abstract.params(feature: T.any(Symbol, String)).returns(T::Boolean) }
|
246
244
|
def deactivate(feature); end
|
247
245
|
|
246
|
+
# Deactivates the flag, calls the block and restores the previous state of the flag.
|
247
|
+
sig do
|
248
|
+
abstract
|
249
|
+
.type_parameters(:R)
|
250
|
+
.params(
|
251
|
+
feature: T.any(Symbol, String),
|
252
|
+
block: T.proc.returns(T.type_parameter(:R)),
|
253
|
+
)
|
254
|
+
.returns(T.type_parameter(:R))
|
255
|
+
end
|
256
|
+
def do_deactivate(feature, &block); end
|
257
|
+
|
248
258
|
# Returns a hash of Objects that the given flag is turned on for.
|
249
259
|
# The keys are class/model names, values are arrays of IDs of instances/records.
|
250
260
|
#
|
@@ -308,13 +318,13 @@ module SimpleFeatureFlags
|
|
308
318
|
|
309
319
|
private
|
310
320
|
|
311
|
-
|
321
|
+
#: (Array[Object] objects, ?object_id_method: Symbol) -> Hash[String, Array[Object]]
|
312
322
|
def objects_to_hash(objects, object_id_method: CONFIG.default_id_method)
|
313
323
|
objects.group_by { |ob| ob.class.to_s }
|
314
324
|
.transform_values { |arr| arr.map(&object_id_method) }
|
315
325
|
end
|
316
326
|
|
317
|
-
|
327
|
+
#: -> void
|
318
328
|
def import_flags_from_file
|
319
329
|
changes = YAML.load_file(file)
|
320
330
|
changes = { mandatory: [], remove: [] } unless changes.is_a? ::Hash
|
@@ -10,17 +10,17 @@ module SimpleFeatureFlags
|
|
10
10
|
class Generate
|
11
11
|
extend T::Sig
|
12
12
|
|
13
|
-
CONFIG_FILE =
|
13
|
+
CONFIG_FILE = 'simple_feature_flags.yml' #: String
|
14
14
|
|
15
|
-
|
15
|
+
#: Options
|
16
16
|
attr_reader :options
|
17
17
|
|
18
|
-
|
18
|
+
#: (Options options) -> void
|
19
19
|
def initialize(options)
|
20
20
|
@options = options
|
21
21
|
end
|
22
22
|
|
23
|
-
|
23
|
+
#: -> void
|
24
24
|
def run
|
25
25
|
if options.rails
|
26
26
|
generate_for_rails
|
@@ -36,7 +36,7 @@ module SimpleFeatureFlags
|
|
36
36
|
|
37
37
|
private
|
38
38
|
|
39
|
-
|
39
|
+
#: -> void
|
40
40
|
def generate_for_rails
|
41
41
|
::FileUtils.cp_r example_config_dir, destination_dir
|
42
42
|
|
@@ -70,26 +70,20 @@ module SimpleFeatureFlags
|
|
70
70
|
system 'bundle'
|
71
71
|
end
|
72
72
|
|
73
|
-
|
74
|
-
params(
|
75
|
-
file_path: String,
|
76
|
-
regexp: Regexp,
|
77
|
-
block: T.proc.params(arg0: String).returns(String),
|
78
|
-
).void
|
79
|
-
end
|
73
|
+
#: (String file_path, Regexp regexp) { (String arg0) -> String } -> void
|
80
74
|
def file_gsub(file_path, regexp, &block)
|
81
75
|
new_content = File.read(file_path).gsub(regexp, &block)
|
82
76
|
File.binwrite(file_path, new_content)
|
83
77
|
end
|
84
78
|
|
85
|
-
|
79
|
+
#: (String file_path, String line) -> void
|
86
80
|
def file_append(file_path, line)
|
87
81
|
new_content = File.read(file_path)
|
88
82
|
new_content = "#{new_content}\n#{line}\n"
|
89
83
|
File.binwrite(file_path, new_content)
|
90
84
|
end
|
91
85
|
|
92
|
-
|
86
|
+
#: (String dir, ?Integer embed_level) -> void
|
93
87
|
def print_dir_tree(dir, embed_level = 0)
|
94
88
|
padding = ' ' * (embed_level * 2)
|
95
89
|
|
@@ -105,32 +99,32 @@ module SimpleFeatureFlags
|
|
105
99
|
end
|
106
100
|
end
|
107
101
|
|
108
|
-
|
102
|
+
#: -> String
|
109
103
|
def initializer_file
|
110
104
|
::File.join(destination_dir, 'config', 'initializers', 'simple_feature_flags.rb')
|
111
105
|
end
|
112
106
|
|
113
|
-
|
107
|
+
#: -> String
|
114
108
|
def gemfile
|
115
109
|
::File.join(destination_dir, 'Gemfile')
|
116
110
|
end
|
117
111
|
|
118
|
-
|
112
|
+
#: -> String
|
119
113
|
def routes_rb
|
120
114
|
::File.join(destination_dir, 'config', 'routes.rb')
|
121
115
|
end
|
122
116
|
|
123
|
-
|
117
|
+
#: -> String
|
124
118
|
def example_config_dir
|
125
119
|
::File.join(::File.expand_path(__dir__), '..', '..', '..', 'example_files', 'config')
|
126
120
|
end
|
127
121
|
|
128
|
-
|
122
|
+
#: -> String
|
129
123
|
def example_config_file
|
130
124
|
::File.join(example_config_dir, CONFIG_FILE)
|
131
125
|
end
|
132
126
|
|
133
|
-
|
127
|
+
#: -> String
|
134
128
|
def destination_dir
|
135
129
|
if options.rails && !::Dir.new(::Dir.pwd).entries.include?('config')
|
136
130
|
raise IncorrectWorkingDirectoryError,
|
@@ -140,7 +134,7 @@ module SimpleFeatureFlags
|
|
140
134
|
::Dir.pwd
|
141
135
|
end
|
142
136
|
|
143
|
-
|
137
|
+
#: -> String
|
144
138
|
def destination_file
|
145
139
|
@destination_file ||= ::File.join(destination_dir, CONFIG_FILE)
|
146
140
|
end
|
@@ -9,23 +9,23 @@ module SimpleFeatureFlags
|
|
9
9
|
class Options
|
10
10
|
extend T::Sig
|
11
11
|
|
12
|
-
|
12
|
+
#: OptionParser
|
13
13
|
attr_reader :opt_parser
|
14
14
|
|
15
|
-
|
15
|
+
#: bool
|
16
16
|
attr_reader :generate
|
17
17
|
|
18
|
-
|
18
|
+
#: bool
|
19
19
|
attr_reader :rails
|
20
20
|
|
21
|
-
|
21
|
+
#: bool
|
22
22
|
attr_reader :ui
|
23
23
|
|
24
|
-
|
24
|
+
#: (Array[String] args) -> void
|
25
25
|
def initialize(args)
|
26
|
-
@rails =
|
27
|
-
@ui =
|
28
|
-
@generate =
|
26
|
+
@rails = true #: bool
|
27
|
+
@ui = false #: bool
|
28
|
+
@generate = false #: bool
|
29
29
|
|
30
30
|
@opt_parser = ::OptionParser.new do |opts|
|
31
31
|
opts.banner = 'Usage: simple_feature_flags [options]'
|
@@ -7,15 +7,15 @@ module SimpleFeatureFlags
|
|
7
7
|
class Runner
|
8
8
|
extend T::Sig
|
9
9
|
|
10
|
-
|
10
|
+
#: Options
|
11
11
|
attr_reader :options
|
12
12
|
|
13
|
-
|
13
|
+
#: (?Array[String] args) -> void
|
14
14
|
def initialize(args = ARGV)
|
15
15
|
@options = Options.new(args)
|
16
16
|
end
|
17
17
|
|
18
|
-
|
18
|
+
#: -> void
|
19
19
|
def run
|
20
20
|
command_class =
|
21
21
|
if @options.generate
|