module Feature
Feature module provides all methods
-
to set a feature repository
-
to check if a feature (represented by a symbol) is active or inactive
-
for conditional block execution with or without a feature
-
to refresh the feature lists (request them from repository)
@note all features not active will be handled has inactive
Example usage:
repository = SimpleRepository.new repository.add_active_feature(:feature_name) Feature.set_repository(repository) Feature.active?(:feature_name) # => true Feature.inactive?(:inactive_feature) # => false Feature.with(:feature_name) do # code will be executed end
This file provides functionality for testing your code with features activated or deactivated. This file should only be required in test/spec code!
To enable Feature testing capabilities do:
require 'feature/testing'
Public Class Methods
Requests if feature is active
@param [Symbol] feature @return [Boolean]
# File lib/feature.rb, line 67 def self.active?(feature) active_features.include?(feature) end
Return list of active feature flags.
@return [Array] list of symbols
# File lib/feature.rb, line 118 def self.active_features raise 'missing Repository for obtaining feature lists' unless @repository refresh! if @auto_refresh || @perform_initial_refresh || (@next_refresh_after && Time.now > @next_refresh_after) @active_features end
Requests if feature is inactive (or unknown)
@param [Symbol] feature @return [Boolean]
# File lib/feature.rb, line 76 def self.inactive?(feature) !active?(feature) end
Refreshes list of active features from repository. Useful when using an repository with external source.
# File lib/feature.rb, line 55 def self.refresh! @active_features = @repository.active_features @next_refresh_after = Time.now + @refresh_after if @refresh_after @perform_initial_refresh = false end
Execute the code block with the given features active
Example usage:
Feature.run_with_activated(:feature, :another_feature) do # your test code here end
# File lib/feature/testing.rb, line 16 def self.run_with_activated(*features, &blk) with_stashed_config do @active_features.concat(features).uniq! @auto_refresh = false @perform_initial_refresh = false blk.call end end
Execute the code block with the given features deactive
Example usage:
Feature.run_with_deactivated(:feature, :another_feature) do # your test code here end
# File lib/feature/testing.rb, line 31 def self.run_with_deactivated(*features, &blk) with_stashed_config do @active_features -= features @auto_refresh = false @perform_initial_refresh = false blk.call end end
Set the feature repository The given repository has to respond to method 'active_features' with an array of symbols
@param [Object] repository the repository to get the features from @param [Boolean|Integer] refresh optional (default: false) - auto refresh or refresh after given number of seconds
# File lib/feature.rb, line 36 def self.set_repository(repository, refresh = false) unless repository.respond_to?(:active_features) raise ArgumentError, 'given repository does not respond to active_features' end @perform_initial_refresh = true @repository = repository if [true, false].include?(refresh) @auto_refresh = refresh else @auto_refresh = false @refresh_after = refresh @next_refresh_after = Time.now + @refresh_after end end
Return value or execute Proc/lambda depending on Feature status.
@param [Symbol] feature @param [Object] value / lambda to use if feature is active @param [Object] value / lambda to use if feature is inactive
# File lib/feature.rb, line 106 def self.switch(feature, l1, l2) if active?(feature) l1.instance_of?(Proc) ? l1.call : l1 else l2.instance_of?(Proc) ? l2.call : l2 end end
Execute the given block if feature is active
@param [Symbol] feature
# File lib/feature.rb, line 84 def self.with(feature) raise ArgumentError, "no block given to #{__method__}" unless block_given? yield if active?(feature) end
Execute the given code block and store + restore the feature configuration before/after the execution
# File lib/feature/testing.rb, line 42 def self.with_stashed_config @active_features = [] if @active_features.nil? old_features = @active_features.dup old_auto_refresh = @auto_refresh old_perform_initial_refresh = @perform_initial_refresh yield ensure @active_features = old_features @auto_refresh = old_auto_refresh @perform_initial_refresh = old_perform_initial_refresh end
Execute the given block if feature is inactive
@param [Symbol] feature
# File lib/feature.rb, line 94 def self.without(feature) raise ArgumentError, "no block given to #{__method__}" unless block_given? yield if inactive?(feature) end