flipper-sequel 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9edc87b55cd1a0a7581687a82a5f00508735a2c97984f4c489b10c1e14900ca9
4
- data.tar.gz: 29abd2bb586f0fbaa3078576bbe62cecfb4ca665585320f908ee44aa229a409a
3
+ metadata.gz: 3519a5c581ad82919b61c95bf34cbd7a49175dac13264c7af7d45d0430619ba2
4
+ data.tar.gz: eb1ef47eab6e6e7d253a2aa066ac1aae9c8ef7e32f3d964fcec2749f9894ac58
5
5
  SHA512:
6
- metadata.gz: be28416559c7acb7a951e32a328340eb26644024c4a04b90f78ff5635da668ee92770fb4e62473a8d71ff4f893f30cbc10ac47d7bb5692604e13413785165602
7
- data.tar.gz: 752e9f662dde7b2b6c68863e0e791cfcb34dc07613b316a1f79428bf2210bf85676d14d7baa3b8dc2453d318922a7644c764553ad0a9f85aea62f2584150b1af
6
+ metadata.gz: c7167b1b5af764176e44702c78f7a8c3994588eef2c47670aa6614908f2cda14d66b9e881f49f9b35ba8f853f5b1ae8c11c004ca7a9fb701e66887f2a935a219
7
+ data.tar.gz: dc2607e6ecc423924b5886a3bcaef3a58f9ba9f220dbcbeb3297178f6b4ca0214ad62f72528044df07bcac9850c8c25110ee248c1ea728350be780f87cba8f04
@@ -1,6 +1,7 @@
1
1
  require 'set'
2
2
  require 'flipper'
3
3
  require 'sequel'
4
+ require 'flipper/model/sequel'
4
5
 
5
6
  module Flipper
6
7
  module Adapters
@@ -28,12 +29,14 @@ module Flipper
28
29
  ::Sequel::Model.require_valid_table = old
29
30
  end
30
31
 
31
- # Public: The name of the adapter.
32
- attr_reader :name
32
+ VALUE_TO_TEXT_WARNING = <<-EOS
33
+ Your database needs migrated to use the latest Flipper features.
34
+ See https://github.com/flippercloud/flipper/issues/557
35
+ EOS
33
36
 
34
37
  # Public: Initialize a new Sequel adapter instance.
35
38
  #
36
- # name - The Symbol name for this adapter. Optional (default :active_record)
39
+ # name - The Symbol name for this adapter. Optional (default :sequel)
37
40
  # feature_class - The AR class responsible for the features table.
38
41
  # gate_class - The AR class responsible for the gates table.
39
42
  #
@@ -47,6 +50,8 @@ module Flipper
47
50
  @name = options.fetch(:name, :sequel)
48
51
  @feature_class = options.fetch(:feature_class) { Feature }
49
52
  @gate_class = options.fetch(:gate_class) { Gate }
53
+
54
+ warn VALUE_TO_TEXT_WARNING if value_not_text?
50
55
  end
51
56
 
52
57
  # Public: The set of known features.
@@ -129,10 +134,9 @@ module Flipper
129
134
  when :integer
130
135
  set(feature, gate, thing)
131
136
  when :set
132
- begin
133
- @gate_class.create(gate_attrs(feature, gate, thing))
134
- rescue ::Sequel::UniqueConstraintViolation
135
- end
137
+ enable_multi(feature, gate, thing)
138
+ when :json
139
+ set(feature, gate, thing, json: true)
136
140
  else
137
141
  unsupported_data_type gate.data_type
138
142
  end
@@ -153,9 +157,10 @@ module Flipper
153
157
  clear(feature)
154
158
  when :integer
155
159
  set(feature, gate, thing)
160
+ when :json
161
+ delete(feature, gate)
156
162
  when :set
157
- @gate_class.where(gate_attrs(feature, gate, thing))
158
- .delete
163
+ @gate_class.where(gate_attrs(feature, gate, thing, json: gate.data_type == :json)).delete
159
164
  else
160
165
  unsupported_data_type gate.data_type
161
166
  end
@@ -171,27 +176,37 @@ module Flipper
171
176
 
172
177
  def set(feature, gate, thing, options = {})
173
178
  clear_feature = options.fetch(:clear, false)
174
- args = {
175
- feature_key: feature.key,
176
- key: gate.key.to_s,
177
- }
179
+ json_feature = options.fetch(:json, false)
180
+
181
+ raise VALUE_TO_TEXT_WARNING if json_feature && value_not_text?
178
182
 
179
183
  @gate_class.db.transaction do
180
184
  clear(feature) if clear_feature
181
- @gate_class.where(args).delete
185
+ delete(feature, gate)
182
186
 
183
187
  begin
184
- @gate_class.create(gate_attrs(feature, gate, thing))
188
+ @gate_class.create(gate_attrs(feature, gate, thing, json: json_feature))
185
189
  rescue ::Sequel::UniqueConstraintViolation
186
190
  end
187
191
  end
188
192
  end
189
193
 
190
- def gate_attrs(feature, gate, thing)
194
+ def delete(feature, gate)
195
+ @gate_class.where(feature_key: feature.key, key: gate.key.to_s).delete
196
+ end
197
+
198
+ def enable_multi(feature, gate, thing)
199
+ begin
200
+ @gate_class.create(gate_attrs(feature, gate, thing, json: gate.data_type == :json))
201
+ rescue ::Sequel::UniqueConstraintViolation
202
+ end
203
+ end
204
+
205
+ def gate_attrs(feature, gate, thing, json: false)
191
206
  {
192
207
  feature_key: feature.key.to_s,
193
208
  key: gate.key.to_s,
194
- value: thing.value.to_s,
209
+ value: json ? Typecast.to_json(thing.value) : thing.value.to_s,
195
210
  }
196
211
  end
197
212
 
@@ -210,11 +225,21 @@ module Flipper
210
225
  end
211
226
  when :set
212
227
  db_gates.select { |db_gate| db_gate.key == gate.key.to_s }.map(&:value).to_set
228
+ when :json
229
+ if detected_db_gate = db_gates.detect { |db_gate| db_gate.key == gate.key.to_s }
230
+ Typecast.from_json(detected_db_gate.value)
231
+ end
213
232
  else
214
233
  unsupported_data_type gate.data_type
215
234
  end
216
235
  end
217
236
  end
237
+
238
+ # Check if value column is text instead of string
239
+ # See https://github.com/flippercloud/flipper/pull/692
240
+ def value_not_text?
241
+ "text".casecmp(@gate_class.db_schema[:value][:db_type]) != 0
242
+ end
218
243
  end
219
244
  end
220
245
  end
@@ -223,4 +248,4 @@ Flipper.configure do |config|
223
248
  config.adapter { Flipper::Adapters::Sequel.new }
224
249
  end
225
250
 
226
- Sequel::Model.include Flipper::Identifier
251
+ Sequel::Model.include Flipper::Model::Sequel
@@ -0,0 +1,12 @@
1
+ module Flipper
2
+ module Model
3
+ module Sequel
4
+ include Flipper::Identifier
5
+
6
+ # Properties used to evaluate expressions
7
+ def flipper_properties
8
+ {"type" => self.class.name}.update(to_hash.transform_keys(&:to_s))
9
+ end
10
+ end
11
+ end
12
+ end
@@ -1,3 +1,3 @@
1
1
  module Flipper
2
- VERSION = '1.0.0'.freeze
2
+ VERSION = '1.1.0'.freeze
3
3
  end
@@ -9,7 +9,7 @@ class CreateFlipperTablesSequel < Sequel::Migration
9
9
  create_table :flipper_gates do |_t|
10
10
  String :feature_key, null: false
11
11
  String :key, null: false
12
- String :value
12
+ String :value, text: true
13
13
  DateTime :created_at, null: false
14
14
  DateTime :updated_at, null: false
15
15
  primary_key [:feature_key, :key, :value]
@@ -42,5 +42,9 @@ RSpec.describe Flipper::Adapters::Sequel do
42
42
  it "defines #flipper_id on Sequel::Model" do
43
43
  expect(Sequel::Model.ancestors).to include(Flipper::Identifier)
44
44
  end
45
+
46
+ it "defines #flipper_properties on Sequel::Model" do
47
+ expect(Sequel::Model.ancestors).to include(Flipper::Model::Sequel)
48
+ end
45
49
  end
46
50
  end
@@ -0,0 +1,46 @@
1
+ require 'flipper/model/sequel'
2
+
3
+ RSpec.describe Flipper::Model::Sequel do
4
+ before(:each) do
5
+ Sequel::Model.db.run <<-SQL
6
+ CREATE TABLE users (
7
+ id integer PRIMARY KEY,
8
+ name string NOT NULL,
9
+ age integer,
10
+ is_confirmed boolean,
11
+ created_at datetime NOT NULL,
12
+ updated_at datetime NOT NULL
13
+ )
14
+ SQL
15
+
16
+ @User = Class.new(::Sequel::Model(:users)) do
17
+ include Flipper::Model::Sequel
18
+ plugin :timestamps, update_on_create: true
19
+
20
+
21
+ def self.name
22
+ 'User'
23
+ end
24
+ end
25
+ end
26
+
27
+ after(:each) do
28
+ Sequel::Model.db.run("DROP table IF EXISTS `users`")
29
+ end
30
+
31
+ describe "flipper_properties" do
32
+ subject { @User.create(name: "Test", age: 22, is_confirmed: true) }
33
+
34
+ it "includes all attributes" do
35
+ expect(subject.flipper_properties).to eq({
36
+ "type" => "User",
37
+ "id" => subject.id,
38
+ "name" => "Test",
39
+ "age" => 22,
40
+ "is_confirmed" => true,
41
+ "created_at" => subject.created_at,
42
+ "updated_at" => subject.updated_at
43
+ })
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,5 @@
1
+ # Setup sequel for sequel adapter and model specs. We don't want this to happen
2
+ # multiple times or it causes failures. So it lives here.
3
+ require "sequel"
4
+ Sequel::Model.db = Sequel.sqlite(':memory:')
5
+ Sequel.extension :migration, :core_extensions
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flipper-sequel
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Nunemaker
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-08-23 00:00:00.000000000 Z
11
+ date: 2023-12-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: flipper
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 1.0.0
19
+ version: 1.1.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 1.0.0
26
+ version: 1.1.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: sequel
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -55,9 +55,12 @@ files:
55
55
  - flipper-sequel.gemspec
56
56
  - lib/flipper-sequel.rb
57
57
  - lib/flipper/adapters/sequel.rb
58
+ - lib/flipper/model/sequel.rb
58
59
  - lib/flipper/version.rb
59
60
  - lib/generators/flipper/templates/sequel_migration.rb
60
61
  - spec/flipper/adapters/sequel_spec.rb
62
+ - spec/flipper/model/sequel_spec.rb
63
+ - spec/support/sequel_setup.rb
61
64
  - test/adapters/sequel_test.rb
62
65
  homepage: https://www.flippercloud.io/docs/adapters/sequel
63
66
  licenses:
@@ -89,4 +92,6 @@ specification_version: 4
89
92
  summary: Sequel adapter for Flipper
90
93
  test_files:
91
94
  - spec/flipper/adapters/sequel_spec.rb
95
+ - spec/flipper/model/sequel_spec.rb
96
+ - spec/support/sequel_setup.rb
92
97
  - test/adapters/sequel_test.rb