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.
@@ -6,16 +6,18 @@ require 'yaml'
6
6
  module SimpleFeatureFlags
7
7
  # Stores feature flags in memory.
8
8
  class RamStorage < BaseStorage
9
- sig { override.returns(String) }
9
+ # @override
10
+ #: String
10
11
  attr_reader :file
11
12
 
12
- sig { override.returns(T::Array[String]) }
13
+ # @override
14
+ #: Array[String]
13
15
  attr_reader :mandatory_flags
14
16
 
15
- sig { returns(T::Hash[Symbol, T::Hash[String, Object]]) }
17
+ #: Hash[Symbol, Hash[String, Object]]
16
18
  attr_reader :flags
17
19
 
18
- sig { params(file: String).void }
20
+ #: (String file) -> void
19
21
  def initialize(file)
20
22
  @file = file
21
23
  @mandatory_flags = []
@@ -25,7 +27,8 @@ module SimpleFeatureFlags
25
27
  end
26
28
 
27
29
  # Checks whether the flag is active. Returns `true`, `false`, `:globally` or `:partially`
28
- sig { override.params(feature: T.any(Symbol, String)).returns(T.any(Symbol, T::Boolean)) }
30
+ # @override
31
+ #: ((Symbol | String) feature) -> (Symbol | bool)
29
32
  def active(feature)
30
33
  case flags.dig(feature.to_sym, 'active')
31
34
  when 'globally', :globally
@@ -40,7 +43,8 @@ module SimpleFeatureFlags
40
43
  end
41
44
 
42
45
  # Checks whether the flag is active.
43
- sig { override.params(feature: T.any(Symbol, String)).returns(T::Boolean) }
46
+ # @override
47
+ #: ((Symbol | String) feature) -> bool
44
48
  def active?(feature)
45
49
  return true if active(feature)
46
50
 
@@ -48,45 +52,43 @@ module SimpleFeatureFlags
48
52
  end
49
53
 
50
54
  # Checks whether the flag is inactive.
51
- sig { override.params(feature: T.any(Symbol, String)).returns(T::Boolean) }
55
+ # @override
56
+ #: ((Symbol | String) feature) -> bool
52
57
  def inactive?(feature)
53
58
  !active?(feature)
54
59
  end
55
60
 
56
61
  # Checks whether the flag is active globally, for every object.
57
- sig { override.params(feature: T.any(Symbol, String)).returns(T::Boolean) }
62
+ # @override
63
+ #: ((Symbol | String) feature) -> bool
58
64
  def active_globally?(feature)
59
65
  ACTIVE_GLOBALLY.include? T.unsafe(flags.dig(feature.to_sym, 'active'))
60
66
  end
61
67
 
62
68
  # Checks whether the flag is inactive globally, for every object.
63
- sig { override.params(feature: T.any(Symbol, String)).returns(T::Boolean) }
69
+ # @override
70
+ #: ((Symbol | String) feature) -> bool
64
71
  def inactive_globally?(feature)
65
72
  !active_globally?(feature)
66
73
  end
67
74
 
68
75
  # Checks whether the flag is active partially, only for certain objects.
69
- sig { override.params(feature: T.any(Symbol, String)).returns(T::Boolean) }
76
+ # @override
77
+ #: ((Symbol | String) feature) -> bool
70
78
  def active_partially?(feature)
71
79
  ACTIVE_PARTIALLY.include? T.unsafe(flags.dig(feature.to_sym, 'active'))
72
80
  end
73
81
 
74
82
  # Checks whether the flag is inactive partially, only for certain objects.
75
- sig { override.params(feature: T.any(Symbol, String)).returns(T::Boolean) }
83
+ # @override
84
+ #: ((Symbol | String) feature) -> bool
76
85
  def inactive_partially?(feature)
77
86
  !active_partially?(feature)
78
87
  end
79
88
 
80
89
  # Checks whether the flag is active for the given object.
81
- sig do
82
- override
83
- .params(
84
- feature: T.any(Symbol, String),
85
- object: Object,
86
- object_id_method: Symbol,
87
- )
88
- .returns(T::Boolean)
89
- end
90
+ # @override
91
+ #: ((Symbol | String) feature, Object object, ?object_id_method: Symbol) -> bool
90
92
  def active_for?(feature, object, object_id_method: CONFIG.default_id_method)
91
93
  return false unless active?(feature)
92
94
  return true if active_globally?(feature)
@@ -100,21 +102,15 @@ module SimpleFeatureFlags
100
102
  end
101
103
 
102
104
  # Checks whether the flag is inactive for the given object.
103
- sig do
104
- override
105
- .params(
106
- feature: T.any(Symbol, String),
107
- object: Object,
108
- object_id_method: Symbol,
109
- )
110
- .returns(T::Boolean)
111
- end
105
+ # @override
106
+ #: ((Symbol | String) feature, Object object, ?object_id_method: Symbol) -> bool
112
107
  def inactive_for?(feature, object, object_id_method: CONFIG.default_id_method)
113
108
  !active_for?(feature, object, object_id_method: object_id_method)
114
109
  end
115
110
 
116
111
  # Checks whether the flag exists.
117
- sig { override.params(feature: T.any(Symbol, String)).returns(T::Boolean) }
112
+ # @override
113
+ #: ((Symbol | String) feature) -> bool
118
114
  def exists?(feature)
119
115
  return false if [nil, ''].include? flags[feature.to_sym]
120
116
 
@@ -122,19 +118,15 @@ module SimpleFeatureFlags
122
118
  end
123
119
 
124
120
  # Returns the description of the flag if it exists.
125
- sig { override.params(feature: T.any(Symbol, String)).returns(T.nilable(String)) }
121
+ # @override
122
+ #: ((Symbol | String) feature) -> String?
126
123
  def description(feature)
127
- T.unsafe(flags.dig(feature.to_sym, 'description'))
124
+ flags.dig(feature.to_sym, 'description') #: as untyped
128
125
  end
129
126
 
130
127
  # Calls the given block if the flag is active.
131
- sig do
132
- override
133
- .params(
134
- feature: T.any(Symbol, String),
135
- block: T.proc.void,
136
- ).void
137
- end
128
+ # @override
129
+ #: ((Symbol | String) feature) { -> void } -> void
138
130
  def when_active(feature, &block)
139
131
  return unless active?(feature)
140
132
 
@@ -142,13 +134,8 @@ module SimpleFeatureFlags
142
134
  end
143
135
 
144
136
  # Calls the given block if the flag is inactive.
145
- sig do
146
- override
147
- .params(
148
- feature: T.any(Symbol, String),
149
- block: T.proc.void,
150
- ).void
151
- end
137
+ # @override
138
+ #: ((Symbol | String) feature) { -> void } -> void
152
139
  def when_inactive(feature, &block)
153
140
  return unless inactive?(feature)
154
141
 
@@ -156,13 +143,8 @@ module SimpleFeatureFlags
156
143
  end
157
144
 
158
145
  # Calls the given block if the flag is active globally.
159
- sig do
160
- override
161
- .params(
162
- feature: T.any(Symbol, String),
163
- block: T.proc.void,
164
- ).void
165
- end
146
+ # @override
147
+ #: ((Symbol | String) feature) { -> void } -> void
166
148
  def when_active_globally(feature, &block)
167
149
  return unless active_globally?(feature)
168
150
 
@@ -170,13 +152,8 @@ module SimpleFeatureFlags
170
152
  end
171
153
 
172
154
  # Calls the given block if the flag is inactive globally.
173
- sig do
174
- override
175
- .params(
176
- feature: T.any(Symbol, String),
177
- block: T.proc.void,
178
- ).void
179
- end
155
+ # @override
156
+ #: ((Symbol | String) feature) { -> void } -> void
180
157
  def when_inactive_globally(feature, &block)
181
158
  return unless inactive_globally?(feature)
182
159
 
@@ -184,13 +161,8 @@ module SimpleFeatureFlags
184
161
  end
185
162
 
186
163
  # Calls the given block if the flag is active partially.
187
- sig do
188
- override
189
- .params(
190
- feature: T.any(Symbol, String),
191
- block: T.proc.void,
192
- ).void
193
- end
164
+ # @override
165
+ #: ((Symbol | String) feature) { -> void } -> void
194
166
  def when_active_partially(feature, &block)
195
167
  return unless active_partially?(feature)
196
168
 
@@ -198,13 +170,8 @@ module SimpleFeatureFlags
198
170
  end
199
171
 
200
172
  # Calls the given block if the flag is inactive partially.
201
- sig do
202
- override
203
- .params(
204
- feature: T.any(Symbol, String),
205
- block: T.proc.void,
206
- ).void
207
- end
173
+ # @override
174
+ #: ((Symbol | String) feature) { -> void } -> void
208
175
  def when_inactive_partially(feature, &block)
209
176
  return unless inactive_partially?(feature)
210
177
 
@@ -212,15 +179,8 @@ module SimpleFeatureFlags
212
179
  end
213
180
 
214
181
  # Calls the given block if the flag is active for the given object.
215
- sig do
216
- override
217
- .params(
218
- feature: T.any(Symbol, String),
219
- object: Object,
220
- object_id_method: Symbol,
221
- block: T.proc.void,
222
- ).void
223
- end
182
+ # @override
183
+ #: ((Symbol | String) feature, Object object, ?object_id_method: Symbol) { -> void } -> void
224
184
  def when_active_for(feature, object, object_id_method: CONFIG.default_id_method, &block)
225
185
  return unless active_for?(feature, object, object_id_method: object_id_method)
226
186
 
@@ -228,15 +188,8 @@ module SimpleFeatureFlags
228
188
  end
229
189
 
230
190
  # Calls the given block if the flag is inactive for the given object.
231
- sig do
232
- override
233
- .params(
234
- feature: T.any(Symbol, String),
235
- object: Object,
236
- object_id_method: Symbol,
237
- block: T.proc.void,
238
- ).void
239
- end
191
+ # @override
192
+ #: ((Symbol | String) feature, Object object, ?object_id_method: Symbol) { -> void } -> void
240
193
  def when_inactive_for(feature, object, object_id_method: CONFIG.default_id_method, &block)
241
194
  return unless inactive_for?(feature, object, object_id_method: object_id_method)
242
195
 
@@ -244,11 +197,12 @@ module SimpleFeatureFlags
244
197
  end
245
198
 
246
199
  # Activates the given flag. Returns `false` if it does not exist.
247
- sig { override.params(feature: T.any(Symbol, String)).returns(T::Boolean) }
200
+ # @override
201
+ #: ((Symbol | String) feature) -> bool
248
202
  def activate(feature)
249
203
  return false unless exists?(feature)
250
204
 
251
- flag = T.must flags[feature.to_sym]
205
+ flag = flags[feature.to_sym] #: as !nil
252
206
  flag['active'] = 'globally'
253
207
 
254
208
  true
@@ -256,26 +210,45 @@ module SimpleFeatureFlags
256
210
 
257
211
  alias activate_globally activate
258
212
 
213
+ # @override
214
+ #: [R] ((Symbol | String) feature) { -> R } -> R
215
+ def do_activate(feature, &block)
216
+ feature = feature.to_sym
217
+ prev_value = flags.dig(feature, 'active')
218
+ activate(feature)
219
+ block.call
220
+ ensure
221
+ T.unsafe(flags)[feature]['active'] = prev_value
222
+ end
223
+
224
+ alias do_activate_globally do_activate
225
+
259
226
  # Activates the given flag partially. Returns `false` if it does not exist.
260
- sig { override.params(feature: T.any(Symbol, String)).returns(T::Boolean) }
227
+ # @override
228
+ #: ((Symbol | String) feature) -> bool
261
229
  def activate_partially(feature)
262
230
  return false unless exists?(feature)
263
231
 
264
- flag = T.must flags[feature.to_sym]
232
+ flag = flags[feature.to_sym] #: as !nil
265
233
  flag['active'] = 'partially'
266
234
 
267
235
  true
268
236
  end
269
237
 
270
- # Activates the given flag for the given objects. Returns `false` if it does not exist.
271
- sig do
272
- override
273
- .params(
274
- feature: T.any(Symbol, String),
275
- objects: Object,
276
- object_id_method: Symbol,
277
- ).void
238
+ # @override
239
+ #: [R] ((Symbol | String) feature) { -> R } -> R
240
+ def do_activate_partially(feature, &block)
241
+ feature = feature.to_sym
242
+ prev_value = flags.dig(feature, 'active')
243
+ activate_partially(feature)
244
+ block.call
245
+ ensure
246
+ T.unsafe(flags)[feature]['active'] = prev_value
278
247
  end
248
+
249
+ # Activates the given flag for the given objects. Returns `false` if it does not exist.
250
+ # @override
251
+ #: ((Symbol | String) feature, *Object objects, ?object_id_method: Symbol) -> void
279
252
  def activate_for(feature, *objects, object_id_method: CONFIG.default_id_method)
280
253
  return false unless exists?(feature)
281
254
 
@@ -288,7 +261,7 @@ module SimpleFeatureFlags
288
261
  active_objects_hash[klass]&.concat(ids)&.uniq!&.sort! # rubocop:disable Style/SafeNavigationChainLength
289
262
  end
290
263
 
291
- flag = T.must flags[feature.to_sym]
264
+ flag = flags[feature.to_sym] #: as !nil
292
265
  flag['active_for_objects'] = active_objects_hash
293
266
 
294
267
  true
@@ -296,14 +269,8 @@ module SimpleFeatureFlags
296
269
 
297
270
  # Activates the given flag for the given objects and sets the flag as partially active.
298
271
  # Returns `false` if it does not exist.
299
- sig do
300
- override
301
- .params(
302
- feature: T.any(Symbol, String),
303
- objects: Object,
304
- object_id_method: Symbol,
305
- ).void
306
- end
272
+ # @override
273
+ #: ((Symbol | String) feature, *Object objects, ?object_id_method: Symbol) -> void
307
274
  def activate_for!(feature, *objects, object_id_method: CONFIG.default_id_method)
308
275
  return false unless T.unsafe(self).activate_for(feature, *objects, object_id_method: object_id_method)
309
276
 
@@ -313,11 +280,12 @@ module SimpleFeatureFlags
313
280
  # Deactivates the given flag for all objects.
314
281
  # Resets the list of objects that this flag has been turned on for.
315
282
  # Returns `false` if it does not exist.
316
- sig { override.params(feature: T.any(Symbol, String)).returns(T::Boolean) }
283
+ # @override
284
+ #: ((Symbol | String) feature) -> bool
317
285
  def deactivate!(feature)
318
286
  return false unless exists?(feature)
319
287
 
320
- flag = T.must flags[feature.to_sym]
288
+ flag = flags[feature.to_sym] #: as !nil
321
289
  flag['active'] = 'false'
322
290
  flag['active_for_objects'] = nil
323
291
 
@@ -327,16 +295,28 @@ module SimpleFeatureFlags
327
295
  # Deactivates the given flag globally.
328
296
  # Does not reset the list of objects that this flag has been turned on for.
329
297
  # Returns `false` if it does not exist.
330
- sig { override.params(feature: T.any(Symbol, String)).returns(T::Boolean) }
298
+ # @override
299
+ #: ((Symbol | String) feature) -> bool
331
300
  def deactivate(feature)
332
301
  return false unless exists?(feature)
333
302
 
334
- flag = T.must flags[feature.to_sym]
303
+ flag = flags[feature.to_sym] #: as !nil
335
304
  flag['active'] = 'false'
336
305
 
337
306
  true
338
307
  end
339
308
 
309
+ # @override
310
+ #: [R] ((Symbol | String) feature) { -> R } -> R
311
+ def do_deactivate(feature, &block)
312
+ feature = feature.to_sym
313
+ prev_value = flags.dig(feature, 'active')
314
+ deactivate(feature)
315
+ block.call
316
+ ensure
317
+ T.unsafe(flags)[feature]['active'] = prev_value
318
+ end
319
+
340
320
  # Returns a hash of Objects that the given flag is turned on for.
341
321
  # The keys are class/model names, values are arrays of IDs of instances/records.
342
322
  #
@@ -344,24 +324,15 @@ module SimpleFeatureFlags
344
324
  #
345
325
  # { "Page" => [25, 89], "Book" => [152] }
346
326
  #
347
- sig do
348
- override
349
- .params(feature: T.any(Symbol, String))
350
- .returns(T::Hash[String, T::Array[Object]])
351
- end
327
+ # @override
328
+ #: ((Symbol | String) feature) -> Hash[String, Array[Object]]
352
329
  def active_objects(feature)
353
330
  T.unsafe(flags.dig(feature.to_sym, 'active_for_objects')) || {}
354
331
  end
355
332
 
356
333
  # Deactivates the given flag for the given objects. Returns `false` if it does not exist.
357
- sig do
358
- override
359
- .params(
360
- feature: T.any(Symbol, String),
361
- objects: Object,
362
- object_id_method: Symbol,
363
- ).void
364
- end
334
+ # @override
335
+ #: ((Symbol | String) feature, *Object objects, ?object_id_method: Symbol) -> void
365
336
  def deactivate_for(feature, *objects, object_id_method: CONFIG.default_id_method)
366
337
  return false unless exists?(feature)
367
338
 
@@ -376,38 +347,28 @@ module SimpleFeatureFlags
376
347
  active_ids.reject! { |id| ids_to_remove.include? id }
377
348
  end
378
349
 
379
- flag = T.must flags[feature.to_sym]
350
+ flag = flags[feature.to_sym] #: as !nil
380
351
  flag['active_for_objects'] = active_objects_hash
381
352
 
382
353
  true
383
354
  end
384
355
 
385
356
  # Returns the data of the flag in a hash.
386
- sig do
387
- override
388
- .params(
389
- feature: T.any(Symbol, String),
390
- ).returns(T.nilable(T::Hash[String, T.anything]))
391
- end
357
+ # @override
358
+ #: ((Symbol | String) feature) -> Hash[String, top]?
392
359
  def get(feature)
393
360
  return unless exists?(feature)
394
361
 
395
- flag = T.must flags[feature.to_sym]
362
+ flag = flags[feature.to_sym] #: as !nil
396
363
  flag['mandatory'] = mandatory_flags.include?(feature.to_s)
397
364
 
398
365
  flag
399
366
  end
400
367
 
401
368
  # Adds the given feature flag.
402
- sig do
403
- override
404
- .params(
405
- feature: T.any(Symbol, String),
406
- description: String,
407
- active: T.any(String, Symbol, T::Boolean, NilClass),
408
- ).returns(T.nilable(T::Hash[String, T.anything]))
409
- end
410
- def add(feature, description, active = 'false')
369
+ # @override
370
+ #: ((Symbol | String) feature, ?String description, ?(String | Symbol | bool)? active) -> Hash[String, top]?
371
+ def add(feature, description = '', active = 'false')
411
372
  return if exists?(feature)
412
373
 
413
374
  active = if ACTIVE_GLOBALLY.include?(active)
@@ -429,12 +390,8 @@ module SimpleFeatureFlags
429
390
 
430
391
  # Removes the given feature flag.
431
392
  # Returns its data or nil if it does not exist.
432
- sig do
433
- override
434
- .params(
435
- feature: T.any(Symbol, String),
436
- ).returns(T.nilable(T::Hash[String, T.anything]))
437
- end
393
+ # @override
394
+ #: ((Symbol | String) feature) -> Hash[String, top]?
438
395
  def remove(feature)
439
396
  return unless exists?(feature)
440
397
 
@@ -445,9 +402,8 @@ module SimpleFeatureFlags
445
402
  end
446
403
 
447
404
  # Returns the data of all feature flags.
448
- sig do
449
- override.returns(T::Array[T::Hash[String, T.anything]])
450
- end
405
+ # @override
406
+ #: -> Array[Hash[String, top]]
451
407
  def all
452
408
  hashes = []
453
409