simple_feature_flags 1.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a84d6f21fb85142181cf9396572ffb07ba4cb6d1573064c3ea984ab339371ddc
4
- data.tar.gz: ca84facde85a613ceb6ecd54a88139a5ff9996838d8463d607e2e8ef93a1ce8e
3
+ metadata.gz: a31152f17215cd2905c721f27217aaa187c006345a5c811ca6194ae36fabef89
4
+ data.tar.gz: 9df276339edd478dc86e0ce590518c21ebc115f63899fe493ad328d11180ae5d
5
5
  SHA512:
6
- metadata.gz: f74fb3b884d0523845038311ce962c5d41e24715f78f7580d1e45889c74eba9df1acd02ce37a6d6ac4e51208fb1d0b6dca0d76a097d90ebf8b367dbb46296996
7
- data.tar.gz: e554a51da1a596189a62857ac4a4bf18ffac37578fece7680f5455222380763e4d1c55a952107b262955533cdfac8ebc7a0211f2c2378dad49d8768c7170da23
6
+ metadata.gz: 8b02dde3a77725c376a0375d8c291e308ee5ce8e7b885e2e051a08e8205eb8407b64e460e43ee6a404a504dd9f9bf1248f387a6764870ec444c3c44f0b423f71
7
+ data.tar.gz: f3f1cdecad7872b6c10c3a1e086f773844e04bf3869fc07d6661fef81dcf33fdb78f2d731318b3f6410cc6ca039fb10625bedb4ffc854f865b0ccf3cfe98f1b6
@@ -31,7 +31,7 @@ jobs:
31
31
  REDIS_PORT: 6379
32
32
  strategy:
33
33
  matrix:
34
- ruby-version: ['3.1', '3.2', '3.3']
34
+ ruby-version: ['3.2', '3.3', '3.4']
35
35
  steps:
36
36
  - name: Checkout code
37
37
  uses: actions/checkout@v3
data/.rubocop.yml CHANGED
@@ -24,8 +24,11 @@ Sorbet/ForbidTUnsafe:
24
24
  Naming/BlockForwarding:
25
25
  Enabled: false
26
26
 
27
+ Sorbet/ForbidSig:
28
+ Enabled: false
29
+
27
30
  AllCops:
28
- TargetRubyVersion: 3.1.0
31
+ TargetRubyVersion: 3.2.0
29
32
  EnabledByDefault: true
30
33
  Exclude:
31
34
  - 'bin/*'
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.3.6
1
+ 3.4.3
data/Gemfile CHANGED
@@ -10,7 +10,7 @@ gem 'minitest', '~> 5.0' # test library
10
10
  gem 'rake', '~> 13.0' # automation tasks
11
11
  gem 'redis', '~> 5.3' # redis client
12
12
  gem 'redis-namespace', '~> 1.11' # namespaces for redis
13
- gem 'rubocop-espago', '~> 1.0' # ruby linter
14
- gem 'rubocop-sorbet', '~> 0.8' # rubocop for sorbet
15
- gem 'sorbet', '>= 0.5' # static typechecker
16
- gem 'tapioca', '> 0.13' # RBI generator for sorbet
13
+ gem 'rubocop-espago', '~> 1.1' # ruby linter
14
+ gem 'rubocop-sorbet', '~> 0.10' # rubocop for sorbet
15
+ gem 'sorbet', '~> 0.5' # static typechecker
16
+ gem 'tapioca', '~> 0.17' # RBI generator for sorbet
data/Gemfile.lock CHANGED
@@ -1,80 +1,96 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- simple_feature_flags (1.3.0)
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
- ast (2.4.2)
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.0)
14
- json (2.8.2)
15
- language_server-protocol (3.17.0.3)
14
+ erubi (1.13.1)
15
+ json (2.10.2)
16
+ language_server-protocol (3.17.0.4)
17
+ lint_roller (1.1.0)
18
+ logger (1.7.0)
16
19
  minitest (5.25.1)
17
20
  netrc (0.11.0)
18
- parallel (1.26.3)
19
- parser (3.3.6.0)
21
+ parallel (1.27.0)
22
+ parser (3.3.8.0)
20
23
  ast (~> 2.4.1)
21
24
  racc
22
- prism (1.2.0)
25
+ prism (1.4.0)
23
26
  racc (1.8.1)
24
27
  rainbow (3.1.1)
25
28
  rake (13.2.1)
26
- rbi (0.2.1)
29
+ rbi (0.3.6)
27
30
  prism (~> 1.0)
28
- sorbet-runtime (>= 0.5.9204)
31
+ rbs (>= 3.4.4)
32
+ rbs (4.0.0.dev.4)
33
+ logger
34
+ prism (>= 1.3.0)
29
35
  redis (5.3.0)
30
36
  redis-client (>= 0.22.0)
31
37
  redis-client (0.22.2)
32
38
  connection_pool
33
39
  redis-namespace (1.11.0)
34
40
  redis (>= 4)
35
- regexp_parser (2.9.2)
36
- rubocop (1.68.0)
41
+ regexp_parser (2.10.0)
42
+ require-hooks (0.2.2)
43
+ rexml (3.4.1)
44
+ rubocop (1.74.0)
37
45
  json (~> 2.3)
38
- language_server-protocol (>= 3.17.0)
46
+ language_server-protocol (~> 3.17.0.2)
47
+ lint_roller (~> 1.1.0)
39
48
  parallel (~> 1.10)
40
49
  parser (>= 3.3.0.2)
41
50
  rainbow (>= 2.2.2, < 4.0)
42
- regexp_parser (>= 2.4, < 3.0)
43
- rubocop-ast (>= 1.32.2, < 2.0)
51
+ regexp_parser (>= 2.9.3, < 3.0)
52
+ rubocop-ast (>= 1.38.0, < 2.0)
44
53
  ruby-progressbar (~> 1.7)
45
- unicode-display_width (>= 2.4.0, < 3.0)
46
- rubocop-ast (1.36.1)
47
- parser (>= 3.3.1.0)
48
- rubocop-espago (1.1.5)
54
+ unicode-display_width (>= 2.4.0, < 4.0)
55
+ rubocop-ast (1.42.0)
56
+ parser (>= 3.3.7.2)
57
+ rubocop-espago (1.1.8)
49
58
  rubocop
50
- rubocop-sorbet (0.8.7)
59
+ rubocop-sorbet (0.10.0)
51
60
  rubocop (>= 1)
52
61
  ruby-progressbar (1.13.0)
53
- sorbet (0.5.11647)
54
- sorbet-static (= 0.5.11647)
55
- sorbet-runtime (0.5.11647)
56
- sorbet-static (0.5.11647-aarch64-linux)
57
- sorbet-static (0.5.11647-universal-darwin)
58
- sorbet-static (0.5.11647-x86_64-linux)
59
- sorbet-static-and-runtime (0.5.11647)
60
- sorbet (= 0.5.11647)
61
- sorbet-runtime (= 0.5.11647)
62
- spoom (1.5.0)
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)
63
72
  erubi (>= 1.10.0)
64
73
  prism (>= 0.28.0)
74
+ rbi (>= 0.3.3)
75
+ rbs (>= 4.0.0.dev.4)
76
+ rexml (>= 3.2.6)
65
77
  sorbet-static-and-runtime (>= 0.5.10187)
66
78
  thor (>= 0.19.2)
67
- tapioca (0.16.4)
79
+ tapioca (0.17.5)
80
+ benchmark
68
81
  bundler (>= 2.2.25)
69
82
  netrc (>= 0.11.0)
70
83
  parallel (>= 1.21.0)
71
- rbi (~> 0.2)
84
+ rbi (>= 0.3.1)
85
+ require-hooks (>= 0.2.2)
72
86
  sorbet-static-and-runtime (>= 0.5.11087)
73
- spoom (>= 1.2.0)
87
+ spoom (>= 1.7.0)
74
88
  thor (>= 1.2.0)
75
89
  yard-sorbet
76
90
  thor (1.3.2)
77
- unicode-display_width (2.6.0)
91
+ unicode-display_width (3.1.4)
92
+ unicode-emoji (~> 4.0, >= 4.0.4)
93
+ unicode-emoji (4.0.4)
78
94
  yard (0.9.37)
79
95
  yard-sorbet (0.9.0)
80
96
  sorbet-runtime
@@ -91,11 +107,11 @@ DEPENDENCIES
91
107
  rake (~> 13.0)
92
108
  redis (~> 5.3)
93
109
  redis-namespace (~> 1.11)
94
- rubocop-espago (~> 1.0)
95
- rubocop-sorbet (~> 0.8)
110
+ rubocop-espago (~> 1.1)
111
+ rubocop-sorbet (~> 0.10)
96
112
  simple_feature_flags!
97
- sorbet (>= 0.5)
98
- tapioca (> 0.13)
113
+ sorbet (~> 0.5)
114
+ tapioca (~> 0.17)
99
115
 
100
116
  BUNDLED WITH
101
- 2.5.22
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) }
@@ -166,14 +164,50 @@ module SimpleFeatureFlags
166
164
  sig { abstract.params(feature: T.any(Symbol, String)).returns(T::Boolean) }
167
165
  def activate(feature); end
168
166
 
167
+ # Activates the flag, calls the block and restores the previous state of the flag.
168
+ sig do
169
+ abstract
170
+ .type_parameters(:R)
171
+ .params(
172
+ feature: T.any(Symbol, String),
173
+ block: T.proc.returns(T.type_parameter(:R)),
174
+ )
175
+ .returns(T.type_parameter(:R))
176
+ end
177
+ def do_activate(feature, &block); end
178
+
169
179
  # Activates the given flag globally. Returns `false` if it does not exist.
170
180
  sig { abstract.params(feature: T.any(Symbol, String)).returns(T::Boolean) }
171
181
  def activate_globally(feature); end
172
182
 
183
+ # Activates the flag globally, calls the block and restores the previous state of the flag.
184
+ sig do
185
+ abstract
186
+ .type_parameters(:R)
187
+ .params(
188
+ feature: T.any(Symbol, String),
189
+ block: T.proc.returns(T.type_parameter(:R)),
190
+ )
191
+ .returns(T.type_parameter(:R))
192
+ end
193
+ def do_activate_globally(feature, &block); end
194
+
173
195
  # Activates the given flag partially. Returns `false` if it does not exist.
174
196
  sig { abstract.params(feature: T.any(Symbol, String)).returns(T::Boolean) }
175
197
  def activate_partially(feature); end
176
198
 
199
+ # Activates the flag partially, calls the block and restores the previous state of the flag.
200
+ sig do
201
+ abstract
202
+ .type_parameters(:R)
203
+ .params(
204
+ feature: T.any(Symbol, String),
205
+ block: T.proc.returns(T.type_parameter(:R)),
206
+ )
207
+ .returns(T.type_parameter(:R))
208
+ end
209
+ def do_activate_partially(feature, &block); end
210
+
177
211
  # Activates the given flag for the given objects. Returns `false` if it does not exist.
178
212
  sig do
179
213
  abstract
@@ -209,6 +243,18 @@ module SimpleFeatureFlags
209
243
  sig { abstract.params(feature: T.any(Symbol, String)).returns(T::Boolean) }
210
244
  def deactivate(feature); end
211
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
+
212
258
  # Returns a hash of Objects that the given flag is turned on for.
213
259
  # The keys are class/model names, values are arrays of IDs of instances/records.
214
260
  #
@@ -252,7 +298,7 @@ module SimpleFeatureFlags
252
298
  active: T.any(String, Symbol, T::Boolean, NilClass),
253
299
  ).returns(T.nilable(T::Hash[String, T.anything]))
254
300
  end
255
- def add(feature, description, active = 'false'); end
301
+ def add(feature, description = '', active = 'false'); end
256
302
 
257
303
  # Removes the given feature flag.
258
304
  # Returns its data or nil if it does not exist.
@@ -272,13 +318,13 @@ module SimpleFeatureFlags
272
318
 
273
319
  private
274
320
 
275
- sig { params(objects: T::Array[Object], object_id_method: Symbol).returns(T::Hash[String, T::Array[Object]]) }
321
+ #: (Array[Object] objects, ?object_id_method: Symbol) -> Hash[String, Array[Object]]
276
322
  def objects_to_hash(objects, object_id_method: CONFIG.default_id_method)
277
323
  objects.group_by { |ob| ob.class.to_s }
278
324
  .transform_values { |arr| arr.map(&object_id_method) }
279
325
  end
280
326
 
281
- sig { void }
327
+ #: -> void
282
328
  def import_flags_from_file
283
329
  changes = YAML.load_file(file)
284
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 = T.let('simple_feature_flags.yml', String)
13
+ CONFIG_FILE = 'simple_feature_flags.yml' #: String
14
14
 
15
- sig { returns(Options) }
15
+ #: Options
16
16
  attr_reader :options
17
17
 
18
- sig { params(options: Options).void }
18
+ #: (Options options) -> void
19
19
  def initialize(options)
20
20
  @options = options
21
21
  end
22
22
 
23
- sig { void }
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
- sig { void }
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
- sig do
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
- sig { params(file_path: String, line: String).void }
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
- sig { params(dir: String, embed_level: Integer).void }
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
- sig { returns String }
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
- sig { returns String }
107
+ #: -> String
114
108
  def gemfile
115
109
  ::File.join(destination_dir, 'Gemfile')
116
110
  end
117
111
 
118
- sig { returns String }
112
+ #: -> String
119
113
  def routes_rb
120
114
  ::File.join(destination_dir, 'config', 'routes.rb')
121
115
  end
122
116
 
123
- sig { returns String }
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
- sig { returns String }
122
+ #: -> String
129
123
  def example_config_file
130
124
  ::File.join(example_config_dir, CONFIG_FILE)
131
125
  end
132
126
 
133
- sig { returns String }
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
- sig { returns String }
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
- sig { returns(OptionParser) }
12
+ #: OptionParser
13
13
  attr_reader :opt_parser
14
14
 
15
- sig { returns(T::Boolean) }
15
+ #: bool
16
16
  attr_reader :generate
17
17
 
18
- sig { returns(T::Boolean) }
18
+ #: bool
19
19
  attr_reader :rails
20
20
 
21
- sig { returns(T::Boolean) }
21
+ #: bool
22
22
  attr_reader :ui
23
23
 
24
- sig { params(args: T::Array[String]).void }
24
+ #: (Array[String] args) -> void
25
25
  def initialize(args)
26
- @rails = T.let(true, T::Boolean)
27
- @ui = T.let(false, T::Boolean)
28
- @generate = T.let(false, T::Boolean)
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
- sig { returns(Options) }
10
+ #: Options
11
11
  attr_reader :options
12
12
 
13
- sig { params(args: T::Array[String]).void }
13
+ #: (?Array[String] args) -> void
14
14
  def initialize(args = ARGV)
15
15
  @options = Options.new(args)
16
16
  end
17
17
 
18
- sig { void }
18
+ #: -> void
19
19
  def run
20
20
  command_class =
21
21
  if @options.generate
@@ -6,10 +6,10 @@ module SimpleFeatureFlags
6
6
  class Configuration
7
7
  extend T::Sig
8
8
 
9
- sig { returns(Symbol) }
9
+ #: Symbol
10
10
  attr_accessor :default_id_method
11
11
 
12
- sig { void }
12
+ #: -> void
13
13
  def initialize
14
14
  @default_id_method = :id
15
15
  end