flipper-active_record 1.2.2 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cd8f5a24abcc3c82a2335e17b796fa84721522eb92bf138ebab4146b58da7fdc
|
4
|
+
data.tar.gz: c39a1899083f55078e7ca28e23d8b1363609ca1322be6d4f32cfcd23922440e2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 16b65bea23bf718930e3509b47ba4719ba4baf93dd86bccf69b292130a7732eff1ab7ea9843c9d4a7342e8180cafd08513bcdd14997be5189e6923afe575e499
|
7
|
+
data.tar.gz: '01816a252d70e1a9c0bd7215893c54f6ac5dd9444cf9c86b571455edb9b45b0b6bae6072a1e678d283eb70c067a738071a7b7625ace489464dda551574a36121'
|
@@ -6,10 +6,13 @@ require 'benchmark/ips'
|
|
6
6
|
|
7
7
|
flipper = Flipper.new(Flipper::Adapters::ActiveRecord.new)
|
8
8
|
|
9
|
-
|
10
|
-
|
9
|
+
10.times do |n|
|
10
|
+
2000.times do |i|
|
11
|
+
flipper.enable_actor 'feature' + n.to_s, Flipper::Actor.new("User;#{i}")
|
12
|
+
end
|
11
13
|
end
|
12
14
|
|
13
15
|
Benchmark.ips do |x|
|
14
16
|
x.report("get_all") { flipper.preload_all }
|
17
|
+
x.report("features") { flipper.features }
|
15
18
|
end
|
@@ -21,6 +21,8 @@ module Flipper
|
|
21
21
|
].join
|
22
22
|
|
23
23
|
has_many :gates, foreign_key: "feature_key", primary_key: "key"
|
24
|
+
|
25
|
+
validates :key, presence: true
|
24
26
|
end
|
25
27
|
|
26
28
|
# Private: Do not use outside of this adapter.
|
@@ -30,6 +32,9 @@ module Flipper
|
|
30
32
|
"flipper_gates",
|
31
33
|
Model.table_name_suffix,
|
32
34
|
].join
|
35
|
+
|
36
|
+
validates :feature_key, presence: true
|
37
|
+
validates :key, presence: true
|
33
38
|
end
|
34
39
|
|
35
40
|
VALUE_TO_TEXT_WARNING = <<-EOS
|
@@ -59,7 +64,7 @@ module Flipper
|
|
59
64
|
|
60
65
|
# Public: The set of known features.
|
61
66
|
def features
|
62
|
-
with_connection(@feature_class) { @feature_class.
|
67
|
+
with_connection(@feature_class) { @feature_class.distinct.pluck(:key).to_set }
|
63
68
|
end
|
64
69
|
|
65
70
|
# Public: Adds a feature to the set of known features.
|
@@ -68,9 +73,9 @@ module Flipper
|
|
68
73
|
# race condition, but add is only used by enable/disable which happen
|
69
74
|
# super rarely, so it shouldn't matter in practice
|
70
75
|
@feature_class.transaction do
|
71
|
-
unless @feature_class.where(key: feature.key).
|
76
|
+
unless @feature_class.where(key: feature.key).exists?
|
72
77
|
begin
|
73
|
-
@feature_class.create!
|
78
|
+
@feature_class.create!(key: feature.key)
|
74
79
|
rescue ::ActiveRecord::RecordNotUnique
|
75
80
|
end
|
76
81
|
end
|
data/lib/flipper/version.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
SpecHelpers.silence { require 'flipper/adapters/active_record' }
|
2
|
-
require 'active_support/core_ext/kernel'
|
3
2
|
|
4
3
|
# Turn off migration logging for specs
|
5
4
|
ActiveRecord::Migration.verbose = false
|
@@ -17,212 +16,217 @@ RSpec.describe Flipper::Adapters::ActiveRecord do
|
|
17
16
|
|
18
17
|
[
|
19
18
|
{
|
20
|
-
adapter
|
21
|
-
database
|
19
|
+
"adapter" => "sqlite3",
|
20
|
+
"database" => ":memory:"
|
22
21
|
},
|
23
22
|
|
24
23
|
{
|
25
|
-
adapter
|
26
|
-
encoding
|
27
|
-
username
|
28
|
-
password
|
29
|
-
database
|
30
|
-
port
|
24
|
+
"adapter" => "mysql2",
|
25
|
+
"encoding" => "utf8mb4",
|
26
|
+
"username" => ENV["MYSQL_USER"] || "root",
|
27
|
+
"password" => ENV["MYSQL_PASSWORD"] || "",
|
28
|
+
"database" => ENV["MYSQL_DATABASE"] || "flipper_test",
|
29
|
+
"port" => ENV["DB_PORT"] || 3306
|
31
30
|
},
|
32
31
|
|
33
32
|
{
|
34
|
-
adapter
|
35
|
-
encoding
|
36
|
-
host
|
37
|
-
username
|
38
|
-
password
|
39
|
-
database
|
33
|
+
"adapter" => "postgresql",
|
34
|
+
"encoding" => "unicode",
|
35
|
+
"host" => "127.0.0.1",
|
36
|
+
"username" => ENV["POSTGRES_USER"] || "",
|
37
|
+
"password" => ENV["POSTGRES_PASSWORD"] || "",
|
38
|
+
"database" => ENV["POSTGRES_DATABASE"] || "flipper_test",
|
40
39
|
}
|
41
40
|
].each do |config|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
end
|
48
|
-
|
49
|
-
before(:each) do
|
50
|
-
skip_on_error(ActiveRecord::ConnectionNotEstablished, "#{config[:adapter]} not available") do
|
51
|
-
ActiveRecord::Base.establish_connection(config)
|
52
|
-
CreateFlipperTables.migrate(:up)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
after(:each) do
|
57
|
-
ActiveRecord::Tasks::DatabaseTasks.purge(config)
|
58
|
-
ActiveRecord::Base.connection.close
|
59
|
-
end
|
60
|
-
|
61
|
-
after(:all) do
|
62
|
-
silence { ActiveRecord::Tasks::DatabaseTasks.drop(config) }
|
63
|
-
end
|
64
|
-
|
65
|
-
it_should_behave_like 'a flipper adapter'
|
66
|
-
|
67
|
-
it "works when table doesn't exist" do
|
68
|
-
CreateFlipperTables.migrate(:down)
|
69
|
-
|
70
|
-
Flipper.configuration = nil
|
71
|
-
Flipper.instance = nil
|
72
|
-
|
73
|
-
expect {
|
74
|
-
silence do
|
75
|
-
load 'flipper/adapters/active_record.rb'
|
76
|
-
Flipper::Adapters::ActiveRecord.new
|
41
|
+
context "with #{config['adapter']}" do
|
42
|
+
context "with tables created" do
|
43
|
+
before(:all) do
|
44
|
+
skip_on_error(ActiveRecord::ConnectionNotEstablished, "#{config['adapter']} not available") do
|
45
|
+
silence { ActiveRecord::Tasks::DatabaseTasks.create(config) }
|
77
46
|
end
|
78
|
-
}.not_to raise_error
|
79
|
-
end
|
80
|
-
|
81
|
-
it "should load actor ids fine" do
|
82
|
-
flipper.enable_percentage_of_time(:foo, 1)
|
83
|
-
|
84
|
-
Flipper::Adapters::ActiveRecord::Gate.create!(
|
85
|
-
feature_key: "foo",
|
86
|
-
key: "actors",
|
87
|
-
value: "Organization;4",
|
88
|
-
)
|
89
47
|
|
90
|
-
flipper = Flipper.new(subject)
|
91
|
-
flipper.preload([:foo])
|
92
|
-
end
|
93
|
-
|
94
|
-
context 'requiring "flipper-active_record"' do
|
95
|
-
before do
|
96
48
|
Flipper.configuration = nil
|
97
|
-
|
49
|
+
end
|
98
50
|
|
99
|
-
|
51
|
+
before(:each) do
|
52
|
+
skip_on_error(ActiveRecord::ConnectionNotEstablished, "#{config['adapter']} not available") do
|
53
|
+
ActiveRecord::Base.establish_connection(config)
|
54
|
+
CreateFlipperTables.migrate(:up)
|
55
|
+
end
|
100
56
|
end
|
101
57
|
|
102
|
-
|
103
|
-
|
58
|
+
after(:each) do
|
59
|
+
ActiveRecord::Tasks::DatabaseTasks.purge(config)
|
60
|
+
ActiveRecord::Base.connection.close
|
104
61
|
end
|
105
|
-
end
|
106
62
|
|
107
|
-
|
108
|
-
|
109
|
-
ActiveRecord::Base.clear_active_connections!
|
63
|
+
after(:all) do
|
64
|
+
silence { ActiveRecord::Tasks::DatabaseTasks.drop(config) } unless $skip
|
110
65
|
end
|
111
66
|
|
112
|
-
|
113
|
-
it "does not hold onto connections" do
|
114
|
-
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(false)
|
115
|
-
subject.features
|
116
|
-
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(false)
|
117
|
-
end
|
67
|
+
it_should_behave_like 'a flipper adapter'
|
118
68
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
69
|
+
it "should load actor ids fine" do
|
70
|
+
flipper.enable_percentage_of_time(:foo, 1)
|
71
|
+
|
72
|
+
Flipper::Adapters::ActiveRecord::Gate.create!(
|
73
|
+
feature_key: "foo",
|
74
|
+
key: "actors",
|
75
|
+
value: "Organization;4",
|
76
|
+
)
|
77
|
+
|
78
|
+
flipper = Flipper.new(subject)
|
79
|
+
flipper.preload([:foo])
|
125
80
|
end
|
126
81
|
|
127
|
-
context "
|
128
|
-
|
129
|
-
|
130
|
-
subject.get_all
|
131
|
-
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(false)
|
82
|
+
context "ActiveRecord connection_pool" do
|
83
|
+
before do
|
84
|
+
ActiveRecord::Base.connection_handler.clear_active_connections!
|
132
85
|
end
|
133
86
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
87
|
+
context "#features" do
|
88
|
+
it "does not hold onto connections" do
|
89
|
+
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(false)
|
90
|
+
subject.features
|
91
|
+
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(false)
|
92
|
+
end
|
93
|
+
|
94
|
+
it "does not release previously held connection" do
|
95
|
+
ActiveRecord::Base.connection # establish a new connection
|
96
|
+
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(true)
|
97
|
+
subject.features
|
98
|
+
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(true)
|
99
|
+
end
|
139
100
|
end
|
140
|
-
end
|
141
101
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
102
|
+
context "#get_all" do
|
103
|
+
it "does not hold onto connections" do
|
104
|
+
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(false)
|
105
|
+
subject.get_all
|
106
|
+
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(false)
|
107
|
+
end
|
108
|
+
|
109
|
+
it "does not release previously held connection" do
|
110
|
+
ActiveRecord::Base.connection # establish a new connection
|
111
|
+
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(true)
|
112
|
+
subject.get_all
|
113
|
+
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(true)
|
114
|
+
end
|
153
115
|
end
|
154
116
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
117
|
+
context "#add / #remove / #clear" do
|
118
|
+
let(:feature) { Flipper::Feature.new(:search, subject) }
|
119
|
+
|
120
|
+
it "does not hold onto connections" do
|
121
|
+
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(false)
|
122
|
+
subject.add(feature)
|
123
|
+
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(false)
|
124
|
+
subject.remove(feature)
|
125
|
+
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(false)
|
126
|
+
subject.clear(feature)
|
127
|
+
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(false)
|
128
|
+
end
|
129
|
+
|
130
|
+
it "does not release previously held connection" do
|
131
|
+
ActiveRecord::Base.connection # establish a new connection
|
132
|
+
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(true)
|
133
|
+
subject.add(feature)
|
134
|
+
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(true)
|
135
|
+
subject.remove(feature)
|
136
|
+
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(true)
|
137
|
+
subject.clear(feature)
|
138
|
+
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(true)
|
139
|
+
end
|
164
140
|
end
|
165
|
-
end
|
166
141
|
|
167
|
-
|
168
|
-
|
142
|
+
context "#get_multi" do
|
143
|
+
let(:feature) { Flipper::Feature.new(:search, subject) }
|
144
|
+
|
145
|
+
it "does not hold onto connections" do
|
146
|
+
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(false)
|
147
|
+
subject.get_multi([feature])
|
148
|
+
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(false)
|
149
|
+
end
|
150
|
+
|
151
|
+
it "does not release previously held connection" do
|
152
|
+
ActiveRecord::Base.connection # establish a new connection
|
153
|
+
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(true)
|
154
|
+
subject.get_multi([feature])
|
155
|
+
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(true)
|
156
|
+
end
|
157
|
+
end
|
169
158
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
159
|
+
context "#enable/#disable boolean" do
|
160
|
+
let(:feature) { Flipper::Feature.new(:search, subject) }
|
161
|
+
let(:gate) { feature.gate(:boolean)}
|
162
|
+
|
163
|
+
it "does not hold onto connections" do
|
164
|
+
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(false)
|
165
|
+
subject.enable(feature, gate, gate.wrap(true))
|
166
|
+
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(false)
|
167
|
+
subject.disable(feature, gate, gate.wrap(false))
|
168
|
+
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(false)
|
169
|
+
end
|
170
|
+
|
171
|
+
it "does not release previously held connection" do
|
172
|
+
ActiveRecord::Base.connection # establish a new connection
|
173
|
+
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(true)
|
174
|
+
subject.enable(feature, gate, gate.wrap(true))
|
175
|
+
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(true)
|
176
|
+
subject.disable(feature, gate, gate.wrap(false))
|
177
|
+
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(true)
|
178
|
+
end
|
174
179
|
end
|
175
180
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
+
context "#enable/#disable set" do
|
182
|
+
let(:feature) { Flipper::Feature.new(:search, subject) }
|
183
|
+
let(:gate) { feature.gate(:group) }
|
184
|
+
|
185
|
+
it "does not hold onto connections" do
|
186
|
+
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(false)
|
187
|
+
subject.enable(feature, gate, gate.wrap(:admin))
|
188
|
+
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(false)
|
189
|
+
subject.disable(feature, gate, gate.wrap(:admin))
|
190
|
+
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(false)
|
191
|
+
end
|
192
|
+
|
193
|
+
it "does not release previously held connection" do
|
194
|
+
ActiveRecord::Base.connection # establish a new connection
|
195
|
+
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(true)
|
196
|
+
subject.enable(feature, gate, gate.wrap(:admin))
|
197
|
+
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(true)
|
198
|
+
subject.disable(feature, gate, gate.wrap(:admin))
|
199
|
+
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(true)
|
200
|
+
end
|
181
201
|
end
|
182
202
|
end
|
183
203
|
|
184
|
-
context
|
185
|
-
|
186
|
-
|
204
|
+
context 'requiring "flipper-active_record"' do
|
205
|
+
before do
|
206
|
+
Flipper.configuration = nil
|
207
|
+
Flipper.instance = nil
|
187
208
|
|
188
|
-
|
189
|
-
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(false)
|
190
|
-
subject.enable(feature, gate, gate.wrap(true))
|
191
|
-
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(false)
|
192
|
-
subject.disable(feature, gate, gate.wrap(false))
|
193
|
-
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(false)
|
209
|
+
silence { load 'flipper/adapters/active_record.rb' }
|
194
210
|
end
|
195
211
|
|
196
|
-
it
|
197
|
-
|
198
|
-
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(true)
|
199
|
-
subject.enable(feature, gate, gate.wrap(true))
|
200
|
-
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(true)
|
201
|
-
subject.disable(feature, gate, gate.wrap(false))
|
202
|
-
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(true)
|
212
|
+
it 'configures itself' do
|
213
|
+
expect(Flipper.adapter.adapter).to be_a(Flipper::Adapters::ActiveRecord)
|
203
214
|
end
|
204
215
|
end
|
216
|
+
end
|
205
217
|
|
206
|
-
|
207
|
-
let(:feature) { Flipper::Feature.new(:search, subject) }
|
208
|
-
let(:gate) { feature.gate(:group) }
|
218
|
+
it "works when table doesn't exist" do
|
209
219
|
|
210
|
-
|
211
|
-
|
212
|
-
subject.enable(feature, gate, gate.wrap(:admin))
|
213
|
-
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(false)
|
214
|
-
subject.disable(feature, gate, gate.wrap(:admin))
|
215
|
-
expect(ActiveRecord::Base.connection_handler.active_connections?).to be(false)
|
216
|
-
end
|
220
|
+
Flipper.configuration = nil
|
221
|
+
Flipper.instance = nil
|
217
222
|
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
end
|
223
|
+
Flipper::Adapters.send(:remove_const, :ActiveRecord) if Flipper::Adapters.const_defined?(:ActiveRecord)
|
224
|
+
|
225
|
+
silence do
|
226
|
+
expect {
|
227
|
+
load 'flipper/adapters/active_record.rb'
|
228
|
+
Flipper::Adapters::ActiveRecord.new
|
229
|
+
}.not_to raise_error
|
226
230
|
end
|
227
231
|
end
|
228
232
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flipper-active_record
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.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: 2024-
|
11
|
+
date: 2024-04-17 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.
|
19
|
+
version: 1.3.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.
|
26
|
+
version: 1.3.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: activerecord
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -74,7 +74,7 @@ metadata:
|
|
74
74
|
homepage_uri: https://www.flippercloud.io
|
75
75
|
source_code_uri: https://github.com/flippercloud/flipper
|
76
76
|
bug_tracker_uri: https://github.com/flippercloud/flipper/issues
|
77
|
-
changelog_uri: https://github.com/flippercloud/flipper/releases/tag/v1.
|
77
|
+
changelog_uri: https://github.com/flippercloud/flipper/releases/tag/v1.3.0
|
78
78
|
post_install_message:
|
79
79
|
rdoc_options: []
|
80
80
|
require_paths:
|