lib/flipper/adapters/sequel.rb in flipper-sequel-1.0.0 vs lib/flipper/adapters/sequel.rb in flipper-sequel-1.1.0

- old
+ new

@@ -1,8 +1,9 @@ require 'set' require 'flipper' require 'sequel' +require 'flipper/model/sequel' module Flipper module Adapters class Sequel include ::Flipper::Adapter @@ -26,16 +27,18 @@ end ensure ::Sequel::Model.require_valid_table = old end - # Public: The name of the adapter. - attr_reader :name + VALUE_TO_TEXT_WARNING = <<-EOS + Your database needs migrated to use the latest Flipper features. + See https://github.com/flippercloud/flipper/issues/557 + EOS # Public: Initialize a new Sequel adapter instance. # - # name - The Symbol name for this adapter. Optional (default :active_record) + # name - The Symbol name for this adapter. Optional (default :sequel) # 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 @@ -45,10 +48,12 @@ # can roll your own tables and what not, if you so desire. def initialize(options = {}) @name = options.fetch(:name, :sequel) @feature_class = options.fetch(:feature_class) { Feature } @gate_class = options.fetch(:gate_class) { Gate } + + warn VALUE_TO_TEXT_WARNING if value_not_text? end # Public: The set of known features. def features @feature_class.all.map(&:key).to_set @@ -127,14 +132,13 @@ when :boolean set(feature, gate, thing, clear: true) when :integer set(feature, gate, thing) when :set - begin - @gate_class.create(gate_attrs(feature, gate, thing)) - rescue ::Sequel::UniqueConstraintViolation - end + enable_multi(feature, gate, thing) + when :json + set(feature, gate, thing, json: true) else unsupported_data_type gate.data_type end true @@ -151,13 +155,14 @@ case gate.data_type when :boolean clear(feature) when :integer set(feature, gate, thing) + when :json + delete(feature, gate) when :set - @gate_class.where(gate_attrs(feature, gate, thing)) - .delete + @gate_class.where(gate_attrs(feature, gate, thing, json: gate.data_type == :json)).delete else unsupported_data_type gate.data_type end true @@ -169,31 +174,41 @@ raise "#{data_type} is not supported by this adapter" end def set(feature, gate, thing, options = {}) clear_feature = options.fetch(:clear, false) - args = { - feature_key: feature.key, - key: gate.key.to_s, - } + json_feature = options.fetch(:json, false) + raise VALUE_TO_TEXT_WARNING if json_feature && value_not_text? + @gate_class.db.transaction do clear(feature) if clear_feature - @gate_class.where(args).delete + delete(feature, gate) begin - @gate_class.create(gate_attrs(feature, gate, thing)) + @gate_class.create(gate_attrs(feature, gate, thing, json: json_feature)) rescue ::Sequel::UniqueConstraintViolation end end end - def gate_attrs(feature, gate, thing) + def delete(feature, gate) + @gate_class.where(feature_key: feature.key, key: gate.key.to_s).delete + end + + def enable_multi(feature, gate, thing) + begin + @gate_class.create(gate_attrs(feature, gate, thing, json: gate.data_type == :json)) + rescue ::Sequel::UniqueConstraintViolation + end + end + + def gate_attrs(feature, gate, thing, json: false) { feature_key: feature.key.to_s, key: gate.key.to_s, - value: thing.value.to_s, + value: json ? Typecast.to_json(thing.value) : thing.value.to_s, } end def result_for_feature(feature, db_gates) db_gates ||= [] @@ -208,19 +223,29 @@ if detected_db_gate = db_gates.detect { |db_gate| db_gate.key == gate.key.to_s } detected_db_gate.value end when :set db_gates.select { |db_gate| db_gate.key == gate.key.to_s }.map(&:value).to_set + when :json + if detected_db_gate = db_gates.detect { |db_gate| db_gate.key == gate.key.to_s } + Typecast.from_json(detected_db_gate.value) + end else unsupported_data_type gate.data_type end end end + + # Check if value column is text instead of string + # See https://github.com/flippercloud/flipper/pull/692 + def value_not_text? + "text".casecmp(@gate_class.db_schema[:value][:db_type]) != 0 + end end end end Flipper.configure do |config| config.adapter { Flipper::Adapters::Sequel.new } end -Sequel::Model.include Flipper::Identifier +Sequel::Model.include Flipper::Model::Sequel