Class: Flipper::Adapters::ActiveRecord
- Inherits:
-
Object
- Object
- Flipper::Adapters::ActiveRecord
- Includes:
- Flipper::Adapter
- Defined in:
- lib/flipper/adapters/active_record.rb
Constant Summary collapse
- VALUE_TO_TEXT_WARNING =
<<-EOS Your database needs migrated to use the latest Flipper features. Run `rails generate flipper:update` and `rails db:migrate`. EOS
Instance Method Summary collapse
-
#add(feature) ⇒ Object
Public: Adds a feature to the set of known features.
-
#clear(feature) ⇒ Object
Public: Clears the gate values for a feature.
-
#disable(feature, gate, thing) ⇒ Object
Public: Disables a gate for a given thing.
-
#enable(feature, gate, thing) ⇒ Object
Public: Enables a gate for a given thing.
-
#features ⇒ Object
Public: The set of known features.
-
#get(feature) ⇒ Object
Public: Gets the values for all gates for a given feature.
- #get_all ⇒ Object
- #get_multi(features) ⇒ Object
-
#initialize(options = {}) ⇒ ActiveRecord
constructor
Public: Initialize a new ActiveRecord adapter instance.
-
#remove(feature) ⇒ Object
Public: Removes a feature from the set of known features.
-
#unsupported_data_type(data_type) ⇒ Object
Private.
Methods included from Flipper::Adapter
#default_config, #export, #import, included, #name, #read_only?
Constructor Details
#initialize(options = {}) ⇒ ActiveRecord
Public: Initialize a new ActiveRecord adapter instance.
name - The Symbol name for this adapter. Optional (default :active_record) feature_class - The AR class responsible for the features table. gate_class - The AR class responsible for the gates table.
Allowing the overriding of name is so you can differentiate multiple instances of this adapter from each other, if, for some reason, that is a thing you do.
Allowing the overriding of the default feature/gate classes means you can roll your own tables and what not, if you so desire.
59 60 61 62 63 64 65 |
# File 'lib/flipper/adapters/active_record.rb', line 59 def initialize( = {}) @name = .fetch(:name, :active_record) @feature_class = .fetch(:feature_class) { Feature } @gate_class = .fetch(:gate_class) { Gate } warn VALUE_TO_TEXT_WARNING if value_not_text? end |
Instance Method Details
#add(feature) ⇒ Object
Public: Adds a feature to the set of known features.
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/flipper/adapters/active_record.rb', line 73 def add(feature) with_connection(@feature_class) do # race condition, but add is only used by enable/disable which happen # super rarely, so it shouldn't matter in practice @feature_class.transaction do unless @feature_class.where(key: feature.key).exists? begin @feature_class.create!(key: feature.key) rescue ::ActiveRecord::RecordNotUnique end end end end true end |
#clear(feature) ⇒ Object
Public: Clears the gate values for a feature.
102 103 104 105 |
# File 'lib/flipper/adapters/active_record.rb', line 102 def clear(feature) with_connection(@gate_class) { @gate_class.where(feature_key: feature.key).destroy_all } true end |
#disable(feature, gate, thing) ⇒ Object
Public: Disables a gate for a given thing.
feature - The Flipper::Feature for the gate. gate - The Flipper::Gate to disable. thing - The Flipper::Type being disabled for the gate.
Returns true.
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
# File 'lib/flipper/adapters/active_record.rb', line 190 def disable(feature, gate, thing) case gate.data_type when :boolean clear(feature) when :integer set(feature, gate, thing) when :json delete(feature, gate) when :set with_connection(@gate_class) do @gate_class.where(feature_key: feature.key, key: gate.key, value: thing.value).destroy_all end else unsupported_data_type gate.data_type end true end |
#enable(feature, gate, thing) ⇒ Object
Public: Enables a gate for a given thing.
feature - The Flipper::Feature for the gate. gate - The Flipper::Gate to enable. thing - The Flipper::Type being enabled for the gate.
Returns true.
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
# File 'lib/flipper/adapters/active_record.rb', line 166 def enable(feature, gate, thing) case gate.data_type when :boolean set(feature, gate, thing, clear: true) when :integer set(feature, gate, thing) when :json set(feature, gate, thing, json: true) when :set enable_multi(feature, gate, thing) else unsupported_data_type gate.data_type end true end |
#features ⇒ Object
Public: The set of known features.
68 69 70 |
# File 'lib/flipper/adapters/active_record.rb', line 68 def features with_connection(@feature_class) { @feature_class.distinct.pluck(:key).to_set } end |
#get(feature) ⇒ Object
Public: Gets the values for all gates for a given feature.
Returns a Hash of Flipper::Gate#key => value.
110 111 112 113 |
# File 'lib/flipper/adapters/active_record.rb', line 110 def get(feature) gates = with_connection(@gate_class) { @gate_class.where(feature_key: feature.key).pluck(:key, :value) } result_for_gates(feature, gates) end |
#get_all ⇒ Object
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/flipper/adapters/active_record.rb', line 132 def get_all with_connection(@feature_class) do # query the gates from the db in a single query features = ::Arel::Table.new(@feature_class.table_name.to_sym) gates = ::Arel::Table.new(@gate_class.table_name.to_sym) rows_query = features.join(gates, ::Arel::Nodes::OuterJoin) .on(features[:key].eq(gates[:feature_key])) .project(features[:key].as('feature_key'), gates[:key], gates[:value]) gates = @feature_class.connection.select_rows(rows_query) # group the gates by feature key grouped_gates = gates.inject({}) do |hash, (feature_key, key, value)| hash[feature_key] ||= [] hash[feature_key] << [key, value] hash end # build up the result hash result = Hash.new { |hash, key| hash[key] = default_config } features = grouped_gates.keys.map { |key| Flipper::Feature.new(key, self) } features.each do |feature| result[feature.key] = result_for_gates(feature, grouped_gates[feature.key]) end result end end |
#get_multi(features) ⇒ Object
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/flipper/adapters/active_record.rb', line 115 def get_multi(features) with_connection(@gate_class) do gates = @gate_class.where(feature_key: features.map(&:key)).pluck(:feature_key, :key, :value) grouped_gates = gates.inject({}) do |hash, (feature_key, key, value)| hash[feature_key] ||= [] hash[feature_key] << [key, value] hash end result = {} features.each do |feature| result[feature.key] = result_for_gates(feature, grouped_gates[feature.key]) end result end end |
#remove(feature) ⇒ Object
Public: Removes a feature from the set of known features.
91 92 93 94 95 96 97 98 99 |
# File 'lib/flipper/adapters/active_record.rb', line 91 def remove(feature) with_connection(@feature_class) do @feature_class.transaction do @feature_class.where(key: feature.key).destroy_all clear(feature) end end true end |
#unsupported_data_type(data_type) ⇒ Object
Private
210 211 212 |
# File 'lib/flipper/adapters/active_record.rb', line 210 def unsupported_data_type(data_type) raise "#{data_type} is not supported by this adapter" end |