Module: AbstractFeatureBranch

Extended by:
Forwardable
Defined in:
lib/abstract_feature_branch.rb,
lib/abstract_feature_branch/configuration.rb,
lib/generators/abstract_feature_branch/context_generator.rb,
lib/generators/abstract_feature_branch/install_generator.rb,
lib/abstract_feature_branch/redis/connection_pool_to_redis_adapter.rb

Defined Under Namespace

Modules: FileBeautifier, Generators, Redis Classes: Configuration

Constant Summary collapse

ENV_FEATURE_PREFIX =
"abstract_feature_branch_"
REDIS_HKEY =
"abstract_feature_branch"

Class Method Summary collapse

Class Method Details

.application_featuresObject



87
88
89
90
# File 'lib/abstract_feature_branch.rb', line 87

def application_features
  unload_application_features unless cacheable?
  environment_features(application_environment)
end

.cacheable?Boolean

Returns:

  • (Boolean)


105
106
107
108
109
# File 'lib/abstract_feature_branch.rb', line 105

def cacheable?
  value = downcase_keys(cacheable)[application_environment]
  value = (application_environment != 'development') if value.nil?
  value
end

.clear_store_featuresObject

Gets features array (all features) from storage (e.g. Redis client)



149
150
151
152
153
154
# File 'lib/abstract_feature_branch.rb', line 149

def clear_store_features
  raise 'Feature storage (e.g. Redis) is not setup!' if feature_store.nil?
  feature_store.hkeys(REDIS_HKEY).each do |feature|
    feature_store.hdel(REDIS_HKEY, feature)
  end
end

.configurationObject



30
31
32
# File 'lib/abstract_feature_branch.rb', line 30

def configuration
  @configuration ||= Configuration.new
end

.delete_store_feature(feature) ⇒ Object

Gets feature value (true or false) from storage (e.g. Redis client)



136
137
138
139
140
# File 'lib/abstract_feature_branch.rb', line 136

def delete_store_feature(feature)
  raise 'Feature storage (e.g. Redis) is not setup!' if feature_store.nil?
  feature = feature.to_s
  feature_store.hdel(REDIS_HKEY, feature)
end

.environment_features(environment) ⇒ Object

performance optimization via caching of feature values resolved through environment variable overrides and local features



74
75
76
77
# File 'lib/abstract_feature_branch.rb', line 74

def environment_features(environment)
  @environment_features ||= {}
  @environment_features[environment] ||= load_environment_features(environment)
end

.environment_variable_overridesObject



50
51
52
# File 'lib/abstract_feature_branch.rb', line 50

def environment_variable_overrides
  @environment_variable_overrides ||= load_environment_variable_overrides
end

.featuresObject



65
66
67
# File 'lib/abstract_feature_branch.rb', line 65

def features
  @features ||= load_features
end

.get_store_feature(feature) ⇒ Object

Gets feature value (true or false) from storage (e.g. Redis client)



122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/abstract_feature_branch.rb', line 122

def get_store_feature(feature)
  raise 'Feature storage (e.g. Redis) is not setup!' if feature_store.nil?
  feature = feature.to_s
  value = feature_store.hget(REDIS_HKEY, feature)
  if value.nil?
    matching_feature = get_store_features.find { |store_feature| store_feature.downcase == feature.downcase }
    value = feature_store.hget(REDIS_HKEY, matching_feature) if matching_feature
  end
  return nil if value.nil?
  return 'per_user' if value.to_s.downcase == 'per_user'
  value.to_s.downcase == 'true'
end

.get_store_featuresObject

Gets features array (all features) from storage (e.g. Redis client)



143
144
145
146
# File 'lib/abstract_feature_branch.rb', line 143

def get_store_features
  raise 'Feature storage (e.g. Redis) is not setup!' if feature_store.nil?
  feature_store.hkeys(REDIS_HKEY)
end

.load_application_featuresObject



91
92
93
94
95
96
97
# File 'lib/abstract_feature_branch.rb', line 91

def load_application_features
  AbstractFeatureBranch.load_redis_overrides
  AbstractFeatureBranch.load_environment_variable_overrides
  AbstractFeatureBranch.load_features
  AbstractFeatureBranch.load_local_features
  AbstractFeatureBranch.load_environment_features(application_environment)
end

.load_environment_features(environment) ⇒ Object



78
79
80
81
82
83
84
85
86
# File 'lib/abstract_feature_branch.rb', line 78

def load_environment_features(environment)
  @environment_features ||= {}
  features[environment] ||= {}
  local_features[environment] ||= {}
  @environment_features[environment] = features[environment].
    merge(local_features[environment]).
    merge(environment_variable_overrides).
    merge(redis_overrides)
end

.load_environment_variable_overridesObject



53
54
55
# File 'lib/abstract_feature_branch.rb', line 53

def load_environment_variable_overrides
  @environment_variable_overrides = featureize_keys(downcase_keys(booleanize_values(select_feature_keys(ENV))))
end

.load_featuresObject



68
69
70
71
# File 'lib/abstract_feature_branch.rb', line 68

def load_features
  @features = {}
  load_specific_features(@features, '.yml')
end

.load_local_featuresObject



60
61
62
63
# File 'lib/abstract_feature_branch.rb', line 60

def load_local_features
  @local_features = {}
  load_specific_features(@local_features, '.local.yml')
end

.load_redis_overridesObject



37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/abstract_feature_branch.rb', line 37

def load_redis_overrides
  return (@redis_overrides = {}) if feature_store.nil?
  
  redis_feature_hash = get_store_features.inject({}) do |output, feature|
    output.merge(feature => get_store_feature(feature))
  end
  
  @redis_overrides = downcase_keys(redis_feature_hash)
rescue Exception => error
  AbstractFeatureBranch.logger.error "AbstractFeatureBranch encounter an error in loading Redis Overrides!\n\nError:#{error.full_message}\n\n"
  @redis_overrides = {}
end

.local_featuresObject



57
58
59
# File 'lib/abstract_feature_branch.rb', line 57

def local_features
  @local_features ||= load_local_features
end

.redis_overridesObject



34
35
36
# File 'lib/abstract_feature_branch.rb', line 34

def redis_overrides
  @redis_overrides ||= load_redis_overrides
end

.set_store_feature(feature, value) ⇒ Object

Sets feature value (true or false) in storage (e.g. Redis client)



112
113
114
115
116
117
118
119
# File 'lib/abstract_feature_branch.rb', line 112

def set_store_feature(feature, value)
  raise 'Feature storage (e.g. Redis) is not setup!' if feature_store.nil?
  feature = feature.to_s
  return delete_store_feature(feature) if value.nil?
  value = 'true' if value == true
  value = 'false' if value == false
  feature_store.hset(REDIS_HKEY, feature, value)
end

.toggle_features_for_user(user_id, features) ⇒ Object



156
157
158
159
160
161
162
163
164
# File 'lib/abstract_feature_branch.rb', line 156

def toggle_features_for_user(user_id, features)
  features.each do |name, value|
    if value
      feature_store.sadd("#{ENV_FEATURE_PREFIX}#{name.to_s.downcase}", user_id)
    else
      feature_store.srem("#{ENV_FEATURE_PREFIX}#{name.to_s.downcase}", user_id)
    end
  end
end

.unload_application_featuresObject



98
99
100
101
102
103
104
# File 'lib/abstract_feature_branch.rb', line 98

def unload_application_features
  @redis_overrides = nil
  @environment_variable_overrides = nil
  @features = nil
  @local_features = nil
  @environment_features = nil
end