Class: Flipper::Feature
- Inherits:
-
Object
- Object
- Flipper::Feature
- Defined in:
- lib/flipper/feature.rb
Constant Summary collapse
- InstrumentationName =
Private: The name of instrumentation events.
"feature_operation.#{InstrumentationNamespace}"
Instance Attribute Summary collapse
-
#adapter ⇒ Object
readonly
Private: The adapter this feature should use.
-
#instrumenter ⇒ Object
readonly
Private: What is being used to instrument all the things.
-
#key ⇒ Object
readonly
Internal: Name converted to value safe for adapter.
-
#name ⇒ Object
readonly
Public: The name of the feature.
Instance Method Summary collapse
-
#boolean_gate ⇒ Object
Private.
-
#conditional_gates(gate_values) ⇒ Object
Private.
-
#description ⇒ Object
Public.
-
#disable(thing = Types::Boolean.new(false)) ⇒ Object
Public: Disable this feature for something.
-
#enable(thing = Types::Boolean.new(true)) ⇒ Object
Public: Enable this feature for something.
-
#enabled?(thing = nil) ⇒ Boolean
Public: Check if a feature is enabled for a thing.
-
#gate(name) ⇒ Object
Internal: Finds a gate by name.
-
#gate_for(thing) ⇒ Object
Internal: Find the gate that protects a thing.
-
#gates ⇒ Object
Internal: Gates to check to see if feature is enabled/disabled.
-
#initialize(name, adapter, options = {}) ⇒ Feature
constructor
Internal: Initializes a new feature instance.
-
#inspect ⇒ Object
Public: Pretty string version for debugging.
-
#instrument(operation, thing) ⇒ Object
Private.
-
#non_boolean_gates ⇒ Object
Private.
-
#state ⇒ Object
Public.
Constructor Details
#initialize(name, adapter, options = {}) ⇒ Feature
Internal: Initializes a new feature instance.
name - The Symbol or String name of the feature. adapter - The adapter that will be used to store details about this feature.
options - The Hash of options.
:instrumenter - What to use to instrument all the things.
31 32 33 34 35 36 |
# File 'lib/flipper/feature.rb', line 31 def initialize(name, adapter, = {}) @name = name @key = name.to_s @instrumenter = .fetch(:instrumenter, Flipper::Instrumenters::Noop) @adapter = adapter end |
Instance Attribute Details
#adapter ⇒ Object (readonly)
Private: The adapter this feature should use.
18 19 20 |
# File 'lib/flipper/feature.rb', line 18 def adapter @adapter end |
#instrumenter ⇒ Object (readonly)
Private: What is being used to instrument all the things.
21 22 23 |
# File 'lib/flipper/feature.rb', line 21 def instrumenter @instrumenter end |
#key ⇒ Object (readonly)
Internal: Name converted to value safe for adapter.
15 16 17 |
# File 'lib/flipper/feature.rb', line 15 def key @key end |
#name ⇒ Object (readonly)
Public: The name of the feature.
12 13 14 |
# File 'lib/flipper/feature.rb', line 12 def name @name end |
Instance Method Details
#boolean_gate ⇒ Object
Private
167 168 169 |
# File 'lib/flipper/feature.rb', line 167 def boolean_gate @boolean_gate ||= gate(:boolean) end |
#conditional_gates(gate_values) ⇒ Object
Private
177 178 179 180 181 182 |
# File 'lib/flipper/feature.rb', line 177 def conditional_gates(gate_values) @conditional_gates ||= non_boolean_gates.select { |gate| value = gate_values[gate.key] gate.enabled?(value) } end |
#description ⇒ Object
Public
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/flipper/feature.rb', line 105 def description gate_values = adapter.get(self) boolean_value = gate_values[:boolean] conditional_gates = conditional_gates(gate_values) if boolean_gate.enabled?(boolean_value) boolean_gate.description(boolean_value).capitalize elsif conditional_gates.any? fragments = conditional_gates.map { |gate| value = gate_values[gate.key] gate.description(value) } "Enabled for #{fragments.join(', ')}" else boolean_gate.description(boolean_value).capitalize end end |
#disable(thing = Types::Boolean.new(false)) ⇒ Object
Public: Disable this feature for something.
Returns the result of Flipper::Gate#disable.
55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/flipper/feature.rb', line 55 def disable(thing = Types::Boolean.new(false)) instrument(:disable, thing) { |payload| adapter.add self gate = gate_for(thing) payload[:gate_name] = gate.name if gate.is_a?(Gates::Boolean) adapter.clear self else adapter.disable self, gate, gate.wrap(thing) end } end |
#enable(thing = Types::Boolean.new(true)) ⇒ Object
Public: Enable this feature for something.
Returns the result of Flipper::Gate#enable.
41 42 43 44 45 46 47 48 49 50 |
# File 'lib/flipper/feature.rb', line 41 def enable(thing = Types::Boolean.new(true)) instrument(:enable, thing) { |payload| adapter.add self gate = gate_for(thing) payload[:gate_name] = gate.name adapter.enable self, gate, gate.wrap(thing) } end |
#enabled?(thing = nil) ⇒ Boolean
Public: Check if a feature is enabled for a thing.
Returns true if enabled, false if not.
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/flipper/feature.rb', line 73 def enabled?(thing = nil) instrument(:enabled?, thing) { |payload| gate_values = adapter.get(self) gate = gates.detect { |gate| gate.open?(thing, gate_values[gate.key]) } if gate.nil? false else payload[:gate_name] = gate.name true end } end |
#gate(name) ⇒ Object
Internal: Finds a gate by name.
Returns a Flipper::Gate if found, nil if not.
151 152 153 |
# File 'lib/flipper/feature.rb', line 151 def gate(name) gates.detect { |gate| gate.name == name.to_sym } end |
#gate_for(thing) ⇒ Object
Internal: Find the gate that protects a thing.
thing - The object for which you would like to find a gate
Returns a Flipper::Gate. Raises Flipper::GateNotFound if no gate found for thing
161 162 163 164 |
# File 'lib/flipper/feature.rb', line 161 def gate_for(thing) gates.detect { |gate| gate.protects?(thing) } || raise(GateNotFound.new(thing)) end |
#gates ⇒ Object
Internal: Gates to check to see if feature is enabled/disabled
Returns an array of gates
138 139 140 141 142 143 144 145 146 |
# File 'lib/flipper/feature.rb', line 138 def gates @gates ||= [ Gates::Boolean.new(@name, :instrumenter => @instrumenter), Gates::Group.new(@name, :instrumenter => @instrumenter), Gates::Actor.new(@name, :instrumenter => @instrumenter), Gates::PercentageOfActors.new(@name, :instrumenter => @instrumenter), Gates::PercentageOfRandom.new(@name, :instrumenter => @instrumenter), ] end |
#inspect ⇒ Object
Public: Pretty string version for debugging.
125 126 127 128 129 130 131 132 133 |
# File 'lib/flipper/feature.rb', line 125 def inspect attributes = [ "name=#{name.inspect}", "state=#{state.inspect}", "description=#{description.inspect}", "adapter=#{adapter.name.inspect}", ] "#<#{self.class.name}:#{object_id} #{attributes.join(', ')}>" end |
#instrument(operation, thing) ⇒ Object
Private
185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/flipper/feature.rb', line 185 def instrument(operation, thing) payload = { :feature_name => name, :operation => operation, :thing => thing, } @instrumenter.instrument(InstrumentationName, payload) { payload[:result] = yield(payload) if block_given? } end |
#non_boolean_gates ⇒ Object
Private
172 173 174 |
# File 'lib/flipper/feature.rb', line 172 def non_boolean_gates @non_boolean_gates ||= gates - [boolean_gate] end |
#state ⇒ Object
Public
91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/flipper/feature.rb', line 91 def state gate_values = adapter.get(self) boolean_value = gate_values[:boolean] if boolean_gate.enabled?(boolean_value) :on elsif conditional_gates(gate_values).any? :conditional else :off end end |