Class: SimpleFeatureFlags::RedisStorage
- Inherits:
-
BaseStorage
- Object
- BaseStorage
- SimpleFeatureFlags::RedisStorage
- Defined in:
- lib/simple_feature_flags/redis_storage.rb
Overview
Stores feature flags in Redis.
Instance Attribute Summary collapse
-
#file ⇒ Object
readonly
: String.
-
#mandatory_flags ⇒ Object
readonly
: Array.
-
#redis ⇒ Object
readonly
: (::Redis | ::Redis::Namespace).
Instance Method Summary collapse
-
#activate(feature) ⇒ Object
(also: #activate_globally)
Activates the given flag.
-
#activate_for(feature, *objects, object_id_method: CONFIG.default_id_method) ⇒ Object
Activates the given flag for the given objects.
-
#activate_for!(feature, *objects, object_id_method: CONFIG.default_id_method) ⇒ Object
Activates the given flag for the given objects and sets the flag as partially active.
-
#activate_partially(feature) ⇒ Object
Activates the given flag partially.
-
#active(feature) ⇒ Object
Checks whether the flag is active.
-
#active?(feature) ⇒ Boolean
Checks whether the flag is active.
-
#active_for?(feature, object, object_id_method: CONFIG.default_id_method) ⇒ Boolean
Checks whether the flag is active for the given object.
-
#active_globally?(feature) ⇒ Boolean
Checks whether the flag is active globally, for every object.
-
#active_objects(feature) ⇒ Object
Returns a hash of Objects that the given flag is turned on for.
-
#active_partially?(feature) ⇒ Boolean
Checks whether the flag is active partially, only for certain objects.
-
#add(feature, description = '', active = 'false') ⇒ Object
Adds the given feature flag.
-
#all ⇒ Object
Returns the data of all feature flags.
-
#deactivate(feature) ⇒ Object
Deactivates the given flag globally.
-
#deactivate!(feature) ⇒ Object
Deactivates the given flag for all objects.
-
#deactivate_for(feature, *objects, object_id_method: CONFIG.default_id_method) ⇒ Object
Deactivates the given flag for the given objects.
-
#description(feature) ⇒ Object
Returns the description of the flag if it exists.
-
#do_activate(feature, &block) ⇒ Object
(also: #do_activate_globally)
: [R] ((Symbol | String) feature) { -> R } -> R.
-
#do_activate_partially(feature, &block) ⇒ Object
: [R] ((Symbol | String) feature) { -> R } -> R.
-
#do_deactivate(feature, &block) ⇒ Object
: [R] ((Symbol | String) feature) { -> R } -> R.
-
#exists?(feature) ⇒ Boolean
Checks whether the flag exists.
-
#get(feature) ⇒ Object
Returns the data of the flag in a hash.
-
#inactive?(feature) ⇒ Boolean
Checks whether the flag is inactive.
-
#inactive_for?(feature, object, object_id_method: CONFIG.default_id_method) ⇒ Boolean
Checks whether the flag is inactive for the given object.
-
#inactive_globally?(feature) ⇒ Boolean
Checks whether the flag is inactive globally, for every object.
-
#inactive_partially?(feature) ⇒ Boolean
Checks whether the flag is inactive partially, only for certain objects.
-
#initialize(redis, file) ⇒ RedisStorage
constructor
: ((::Redis | ::Redis::Namespace) redis, String file) -> void.
-
#namespaced_redis ⇒ Object
: -> Redis::Namespace?.
-
#remove(feature) ⇒ Object
Removes the given feature flag.
-
#when_active(feature, &block) ⇒ Object
Calls the given block if the flag is active.
-
#when_active_for(feature, object, object_id_method: CONFIG.default_id_method, &block) ⇒ Object
Calls the given block if the flag is active for the given object.
-
#when_active_globally(feature, &block) ⇒ Object
Calls the given block if the flag is active globally.
-
#when_active_partially(feature, &block) ⇒ Object
Calls the given block if the flag is active partially.
-
#when_inactive(feature, &block) ⇒ Object
Calls the given block if the flag is inactive.
-
#when_inactive_for(feature, object, object_id_method: CONFIG.default_id_method, &block) ⇒ Object
Calls the given block if the flag is inactive for the given object.
-
#when_inactive_globally(feature, &block) ⇒ Object
Calls the given block if the flag is inactive globally.
-
#when_inactive_partially(feature, &block) ⇒ Object
Calls the given block if the flag is inactive partially.
Constructor Details
#initialize(redis, file) ⇒ RedisStorage
: ((::Redis | ::Redis::Namespace) redis, String file) -> void
21 22 23 24 25 26 27 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 21 def initialize(redis, file) @file = file @redis = redis @mandatory_flags = [] import_flags_from_file end |
Instance Attribute Details
#file ⇒ Object (readonly)
: String
11 12 13 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 11 def file @file end |
#mandatory_flags ⇒ Object (readonly)
: Array
15 16 17 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 15 def mandatory_flags @mandatory_flags end |
#redis ⇒ Object (readonly)
: (::Redis | ::Redis::Namespace)
18 19 20 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 18 def redis @redis end |
Instance Method Details
#activate(feature) ⇒ Object Also known as: activate_globally
Activates the given flag. Returns ‘false` if it does not exist. : ((Symbol | String) feature) -> bool
202 203 204 205 206 207 208 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 202 def activate(feature) return false unless exists?(feature) redis.hset(feature.to_s, 'active', 'globally') true end |
#activate_for(feature, *objects, object_id_method: CONFIG.default_id_method) ⇒ Object
Activates the given flag for the given objects. Returns ‘false` if it does not exist. : ((Symbol | String) feature, *Object objects, ?object_id_method: Symbol) -> void
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 250 def activate_for(feature, *objects, object_id_method: CONFIG.default_id_method) return false unless exists?(feature) to_activate_hash = objects_to_hash(objects, object_id_method: object_id_method) active_objects_hash = active_objects(feature) to_activate_hash.each do |klass, ids| (active_objects_hash[klass] = ids) && next unless active_objects_hash[klass] active_objects_hash[klass]&.concat(ids)&.uniq!&.sort! # rubocop:disable Style/SafeNavigationChainLength end redis.hset(feature.to_s, 'active_for_objects', active_objects_hash.to_json) true end |
#activate_for!(feature, *objects, object_id_method: CONFIG.default_id_method) ⇒ Object
Activates the given flag for the given objects and sets the flag as partially active. Returns ‘false` if it does not exist. : ((Symbol | String) feature, *Object objects, ?object_id_method: Symbol) -> void
271 272 273 274 275 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 271 def activate_for!(feature, *objects, object_id_method: CONFIG.default_id_method) return false unless T.unsafe(self).activate_for(feature, *objects, object_id_method: object_id_method) activate_partially(feature) end |
#activate_partially(feature) ⇒ Object
Activates the given flag partially. Returns ‘false` if it does not exist. : ((Symbol | String) feature) -> bool
228 229 230 231 232 233 234 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 228 def activate_partially(feature) return false unless exists?(feature) redis.hset(feature.to_s, 'active', 'partially') true end |
#active(feature) ⇒ Object
Checks whether the flag is active. Returns ‘true`, `false`, `:globally` or `:partially` : ((Symbol | String) feature) -> (Symbol | bool)
32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 32 def active(feature) case redis.hget(feature.to_s, 'active') when 'globally' :globally when 'partially' :partially when 'true', true true else false end end |
#active?(feature) ⇒ Boolean
Checks whether the flag is active. : ((Symbol | String) feature) -> bool
48 49 50 51 52 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 48 def active?(feature) return true if active(feature) false end |
#active_for?(feature, object, object_id_method: CONFIG.default_id_method) ⇒ Boolean
Checks whether the flag is active for the given object. : ((Symbol | String) feature, Object object, ?object_id_method: Symbol) -> bool
92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 92 def active_for?(feature, object, object_id_method: CONFIG.default_id_method) return false unless active?(feature) return true if active_globally?(feature) active_objects_hash = active_objects(feature) active_ids = active_objects_hash[object.class.to_s] return false unless active_ids active_ids.include? object.public_send(object_id_method) end |
#active_globally?(feature) ⇒ Boolean
Checks whether the flag is active globally, for every object. : ((Symbol | String) feature) -> bool
64 65 66 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 64 def active_globally?(feature) ACTIVE_GLOBALLY.include? redis.hget(feature.to_s, 'active') end |
#active_objects(feature) ⇒ Object
Returns a hash of Objects that the given flag is turned on for. The keys are class/model names, values are arrays of IDs of instances/records.
looks like this:
{ "Page" => [25, 89], "Book" => [152] }
: ((Symbol | String) feature) -> Hash[String, Array]
324 325 326 327 328 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 324 def active_objects(feature) ::JSON.parse(redis.hget(feature.to_s, 'active_for_objects').to_s) rescue ::JSON::ParserError {} end |
#active_partially?(feature) ⇒ Boolean
Checks whether the flag is active partially, only for certain objects. : ((Symbol | String) feature) -> bool
78 79 80 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 78 def active_partially?(feature) ACTIVE_PARTIALLY.include? redis.hget(feature.to_s, 'active') end |
#add(feature, description = '', active = 'false') ⇒ Object
Adds the given feature flag. : ((Symbol | String) feature, ?String description, ?(String | Symbol | bool)? active) -> Hash[String, top]?
372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 372 def add(feature, description = '', active = 'false') return if exists?(feature) active = if ACTIVE_GLOBALLY.include?(active) 'globally' elsif ACTIVE_PARTIALLY.include?(active) 'partially' else 'false' end hash = { 'name' => feature.to_s, 'active' => active, 'description' => description, } redis.hset(feature.to_s, hash) hash end |
#all ⇒ Object
Returns the data of all feature flags. : -> Array[Hash[String, top]]
409 410 411 412 413 414 415 416 417 418 419 420 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 409 def all keys = [] hashes = [] redis.scan_each(match: '*') do |key| next if keys.include?(key) keys << key hashes << get(key) end hashes end |
#deactivate(feature) ⇒ Object
Deactivates the given flag globally. Does not reset the list of objects that this flag has been turned on for. Returns ‘false` if it does not exist. : ((Symbol | String) feature) -> bool
296 297 298 299 300 301 302 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 296 def deactivate(feature) return false unless exists?(feature) redis.hset(feature.to_s, 'active', 'false') true end |
#deactivate!(feature) ⇒ Object
Deactivates the given flag for all objects. Resets the list of objects that this flag has been turned on for. Returns ‘false` if it does not exist. : ((Symbol | String) feature) -> bool
282 283 284 285 286 287 288 289 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 282 def deactivate!(feature) return false unless exists?(feature) redis.hset(feature.to_s, 'active', 'false') redis.hset(feature.to_s, 'active_for_objects', '') true end |
#deactivate_for(feature, *objects, object_id_method: CONFIG.default_id_method) ⇒ Object
Deactivates the given flag for the given objects. Returns ‘false` if it does not exist. : ((Symbol | String) feature, *Object objects, ?object_id_method: Symbol) -> void
333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 333 def deactivate_for(feature, *objects, object_id_method: CONFIG.default_id_method) return false unless exists?(feature) active_objects_hash = active_objects(feature) objects_to_deactivate_hash = objects_to_hash(objects, object_id_method: object_id_method) objects_to_deactivate_hash.each do |klass, ids_to_remove| active_ids = active_objects_hash[klass] next unless active_ids active_ids.reject! { |id| ids_to_remove.include? id } end redis.hset(feature.to_s, 'active_for_objects', active_objects_hash.to_json) true end |
#description(feature) ⇒ Object
Returns the description of the flag if it exists. : ((Symbol | String) feature) -> String?
123 124 125 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 123 def description(feature) redis.hget(feature.to_s, 'description') end |
#do_activate(feature, &block) ⇒ Object Also known as: do_activate_globally
: [R] ((Symbol | String) feature) { -> R } -> R
212 213 214 215 216 217 218 219 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 212 def do_activate(feature, &block) feature = feature.to_s prev_value = redis.hget(feature, 'active') activate(feature) block.call ensure redis.hset(feature, 'active', prev_value) end |
#do_activate_partially(feature, &block) ⇒ Object
: [R] ((Symbol | String) feature) { -> R } -> R
238 239 240 241 242 243 244 245 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 238 def do_activate_partially(feature, &block) feature = feature.to_s prev_value = redis.hget(feature, 'active') activate_partially(feature) block.call ensure redis.hset(feature, 'active', prev_value) end |
#do_deactivate(feature, &block) ⇒ Object
: [R] ((Symbol | String) feature) { -> R } -> R
306 307 308 309 310 311 312 313 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 306 def do_deactivate(feature, &block) feature = feature.to_s prev_value = redis.hget(feature, 'active') deactivate(feature) block.call ensure redis.hset(feature, 'active', prev_value) end |
#exists?(feature) ⇒ Boolean
Checks whether the flag exists. : ((Symbol | String) feature) -> bool
114 115 116 117 118 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 114 def exists?(feature) return false if [nil, ''].include? redis.hget(feature.to_s, 'name') true end |
#get(feature) ⇒ Object
Returns the data of the flag in a hash. : ((Symbol | String) feature) -> Hash[String, top]?
355 356 357 358 359 360 361 362 363 364 365 366 367 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 355 def get(feature) return unless exists?(feature) hash = redis.hgetall(feature.to_s) hash['mandatory'] = mandatory_flags.include?(feature.to_s) hash['active_for_objects'] = begin ::JSON.parse(hash['active_for_objects']) rescue StandardError {} end hash end |
#inactive?(feature) ⇒ Boolean
Checks whether the flag is inactive. : ((Symbol | String) feature) -> bool
57 58 59 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 57 def inactive?(feature) !active?(feature) end |
#inactive_for?(feature, object, object_id_method: CONFIG.default_id_method) ⇒ Boolean
Checks whether the flag is inactive for the given object. : ((Symbol | String) feature, Object object, ?object_id_method: Symbol) -> bool
107 108 109 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 107 def inactive_for?(feature, object, object_id_method: CONFIG.default_id_method) !active_for?(feature, object, object_id_method: object_id_method) end |
#inactive_globally?(feature) ⇒ Boolean
Checks whether the flag is inactive globally, for every object. : ((Symbol | String) feature) -> bool
71 72 73 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 71 def inactive_globally?(feature) !active_globally?(feature) end |
#inactive_partially?(feature) ⇒ Boolean
Checks whether the flag is inactive partially, only for certain objects. : ((Symbol | String) feature) -> bool
85 86 87 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 85 def inactive_partially?(feature) !active_partially?(feature) end |
#namespaced_redis ⇒ Object
: -> Redis::Namespace?
423 424 425 426 427 428 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 423 def namespaced_redis r = redis return unless r.is_a?(Redis::Namespace) r end |
#remove(feature) ⇒ Object
Removes the given feature flag. Returns its data or nil if it does not exist. : ((Symbol | String) feature) -> Hash[String, top]?
397 398 399 400 401 402 403 404 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 397 def remove(feature) return unless exists?(feature) removed = get(feature) redis.del(feature.to_s) removed end |
#when_active(feature, &block) ⇒ Object
Calls the given block if the flag is active. : ((Symbol | String) feature) { -> void } -> void
130 131 132 133 134 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 130 def when_active(feature, &block) return unless active?(feature) block.call end |
#when_active_for(feature, object, object_id_method: CONFIG.default_id_method, &block) ⇒ Object
Calls the given block if the flag is active for the given object. : ((Symbol | String) feature, Object object, ?object_id_method: Symbol) { -> void } -> void
184 185 186 187 188 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 184 def when_active_for(feature, object, object_id_method: CONFIG.default_id_method, &block) return unless active_for?(feature, object, object_id_method: object_id_method) block.call end |
#when_active_globally(feature, &block) ⇒ Object
Calls the given block if the flag is active globally. : ((Symbol | String) feature) { -> void } -> void
148 149 150 151 152 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 148 def when_active_globally(feature, &block) return unless active_globally?(feature) block.call end |
#when_active_partially(feature, &block) ⇒ Object
Calls the given block if the flag is active partially. : ((Symbol | String) feature) { -> void } -> void
166 167 168 169 170 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 166 def when_active_partially(feature, &block) return unless active_partially?(feature) block.call end |
#when_inactive(feature, &block) ⇒ Object
Calls the given block if the flag is inactive. : ((Symbol | String) feature) { -> void } -> void
139 140 141 142 143 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 139 def when_inactive(feature, &block) return unless inactive?(feature) block.call end |
#when_inactive_for(feature, object, object_id_method: CONFIG.default_id_method, &block) ⇒ Object
Calls the given block if the flag is inactive for the given object. : ((Symbol | String) feature, Object object, ?object_id_method: Symbol) { -> void } -> void
193 194 195 196 197 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 193 def when_inactive_for(feature, object, object_id_method: CONFIG.default_id_method, &block) return unless inactive_for?(feature, object, object_id_method: object_id_method) block.call end |
#when_inactive_globally(feature, &block) ⇒ Object
Calls the given block if the flag is inactive globally. : ((Symbol | String) feature) { -> void } -> void
157 158 159 160 161 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 157 def when_inactive_globally(feature, &block) return unless inactive_globally?(feature) block.call end |
#when_inactive_partially(feature, &block) ⇒ Object
Calls the given block if the flag is inactive partially. : ((Symbol | String) feature) { -> void } -> void
175 176 177 178 179 |
# File 'lib/simple_feature_flags/redis_storage.rb', line 175 def when_inactive_partially(feature, &block) return unless inactive_partially?(feature) block.call end |