flipper-active_record 1.3.5 → 1.4.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 +4 -4
- data/lib/flipper/adapters/active_record/feature.rb +20 -0
- data/lib/flipper/adapters/active_record/gate.rb +19 -0
- data/lib/flipper/adapters/active_record/model.rb +9 -0
- data/lib/flipper/adapters/active_record.rb +34 -37
- data/lib/flipper/version.rb +1 -1
- data/spec/flipper/adapters/active_record_spec.rb +146 -33
- data/test/adapters/active_record_test.rb +16 -0
- metadata +14 -9
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d550530c982b783d5bb01547b0dd63e65ae28cf684baf5cab91f633b45546a6a
|
|
4
|
+
data.tar.gz: abe3da9138ef86cc0a7fecf5496d4ac78b036cfb9f8188b782debf9be8ab92ba
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fe247ffa161d7090ff3630a50329f128c75b7ef65109b9a9fb85bd4432892752d7f106b21bf05f9cf5de913ed43e72f18d9316e9775300d9cc7be4c571c8f492
|
|
7
|
+
data.tar.gz: 82583bfa629d02c3eeba04b9cb7b32ba78ff65fcb39bba598c07e9a9dc843a486fe3a08351b528db3a1d032a7632593af92a6b1045c0d2af568c30974474c684
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require 'flipper/adapters/active_record/model'
|
|
2
|
+
|
|
3
|
+
module Flipper
|
|
4
|
+
module Adapters
|
|
5
|
+
class ActiveRecord
|
|
6
|
+
# Private: Do not use outside of this adapter.
|
|
7
|
+
class Feature < Model
|
|
8
|
+
self.table_name = [
|
|
9
|
+
Model.table_name_prefix,
|
|
10
|
+
"flipper_features",
|
|
11
|
+
Model.table_name_suffix,
|
|
12
|
+
].join
|
|
13
|
+
|
|
14
|
+
has_many :gates, foreign_key: "feature_key", primary_key: "key"
|
|
15
|
+
|
|
16
|
+
validates :key, presence: true
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require 'flipper/adapters/active_record/model'
|
|
2
|
+
|
|
3
|
+
module Flipper
|
|
4
|
+
module Adapters
|
|
5
|
+
class ActiveRecord
|
|
6
|
+
# Private: Do not use outside of this adapter.
|
|
7
|
+
class Gate < Model
|
|
8
|
+
self.table_name = [
|
|
9
|
+
Model.table_name_prefix,
|
|
10
|
+
"flipper_gates",
|
|
11
|
+
Model.table_name_suffix,
|
|
12
|
+
].join
|
|
13
|
+
|
|
14
|
+
validates :feature_key, presence: true
|
|
15
|
+
validates :key, presence: true
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -2,41 +2,15 @@ require 'set'
|
|
|
2
2
|
require 'securerandom'
|
|
3
3
|
require 'flipper'
|
|
4
4
|
require 'active_record'
|
|
5
|
+
require_relative 'active_record/model'
|
|
6
|
+
require_relative 'active_record/feature'
|
|
7
|
+
require_relative 'active_record/gate'
|
|
5
8
|
|
|
6
9
|
module Flipper
|
|
7
10
|
module Adapters
|
|
8
11
|
class ActiveRecord
|
|
9
12
|
include ::Flipper::Adapter
|
|
10
13
|
|
|
11
|
-
class Model < ::ActiveRecord::Base
|
|
12
|
-
self.abstract_class = true
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
# Private: Do not use outside of this adapter.
|
|
16
|
-
class Feature < Model
|
|
17
|
-
self.table_name = [
|
|
18
|
-
Model.table_name_prefix,
|
|
19
|
-
"flipper_features",
|
|
20
|
-
Model.table_name_suffix,
|
|
21
|
-
].join
|
|
22
|
-
|
|
23
|
-
has_many :gates, foreign_key: "feature_key", primary_key: "key"
|
|
24
|
-
|
|
25
|
-
validates :key, presence: true
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
# Private: Do not use outside of this adapter.
|
|
29
|
-
class Gate < Model
|
|
30
|
-
self.table_name = [
|
|
31
|
-
Model.table_name_prefix,
|
|
32
|
-
"flipper_gates",
|
|
33
|
-
Model.table_name_suffix,
|
|
34
|
-
].join
|
|
35
|
-
|
|
36
|
-
validates :feature_key, presence: true
|
|
37
|
-
validates :key, presence: true
|
|
38
|
-
end
|
|
39
|
-
|
|
40
14
|
VALUE_TO_TEXT_WARNING = <<-EOS
|
|
41
15
|
Your database needs to be migrated to use the latest Flipper features.
|
|
42
16
|
Run `rails generate flipper:update` and `rails db:migrate`.
|
|
@@ -67,7 +41,7 @@ module Flipper
|
|
|
67
41
|
|
|
68
42
|
# Public: Adds a feature to the set of known features.
|
|
69
43
|
def add(feature)
|
|
70
|
-
|
|
44
|
+
with_write_connection(@feature_class) do
|
|
71
45
|
@feature_class.transaction(requires_new: true) do
|
|
72
46
|
begin
|
|
73
47
|
# race condition, but add is only used by enable/disable which happen
|
|
@@ -86,7 +60,7 @@ module Flipper
|
|
|
86
60
|
|
|
87
61
|
# Public: Removes a feature from the set of known features.
|
|
88
62
|
def remove(feature)
|
|
89
|
-
|
|
63
|
+
with_write_connection(@feature_class) do
|
|
90
64
|
@feature_class.transaction do
|
|
91
65
|
@feature_class.where(key: feature.key).destroy_all
|
|
92
66
|
clear(feature)
|
|
@@ -97,7 +71,7 @@ module Flipper
|
|
|
97
71
|
|
|
98
72
|
# Public: Clears the gate values for a feature.
|
|
99
73
|
def clear(feature)
|
|
100
|
-
|
|
74
|
+
with_write_connection(@gate_class) { @gate_class.where(feature_key: feature.key).destroy_all }
|
|
101
75
|
true
|
|
102
76
|
end
|
|
103
77
|
|
|
@@ -126,7 +100,7 @@ module Flipper
|
|
|
126
100
|
end
|
|
127
101
|
end
|
|
128
102
|
|
|
129
|
-
def get_all
|
|
103
|
+
def get_all(**kwargs)
|
|
130
104
|
with_connection(@feature_class) do |connection|
|
|
131
105
|
# query the gates from the db in a single query
|
|
132
106
|
features = ::Arel::Table.new(@feature_class.table_name.to_sym)
|
|
@@ -149,6 +123,7 @@ module Flipper
|
|
|
149
123
|
features.each do |feature|
|
|
150
124
|
result[feature.key] = result_for_gates(feature, grouped_gates[feature.key])
|
|
151
125
|
end
|
|
126
|
+
result.default_proc = nil
|
|
152
127
|
result
|
|
153
128
|
end
|
|
154
129
|
end
|
|
@@ -191,9 +166,11 @@ module Flipper
|
|
|
191
166
|
when :integer
|
|
192
167
|
set(feature, gate, thing)
|
|
193
168
|
when :json
|
|
194
|
-
|
|
169
|
+
with_write_connection(@gate_class) do
|
|
170
|
+
delete(feature, gate)
|
|
171
|
+
end
|
|
195
172
|
when :set
|
|
196
|
-
|
|
173
|
+
with_write_connection(@gate_class) do
|
|
197
174
|
@gate_class.where(feature_key: feature.key, key: gate.key, value: thing.value).destroy_all
|
|
198
175
|
end
|
|
199
176
|
else
|
|
@@ -216,7 +193,7 @@ module Flipper
|
|
|
216
193
|
|
|
217
194
|
raise VALUE_TO_TEXT_WARNING if json_feature && value_not_text?
|
|
218
195
|
|
|
219
|
-
|
|
196
|
+
with_write_connection(@gate_class) do
|
|
220
197
|
@gate_class.transaction(requires_new: true) do
|
|
221
198
|
clear(feature) if clear_feature
|
|
222
199
|
delete(feature, gate)
|
|
@@ -241,7 +218,7 @@ module Flipper
|
|
|
241
218
|
end
|
|
242
219
|
|
|
243
220
|
def enable_multi(feature, gate, thing)
|
|
244
|
-
|
|
221
|
+
with_write_connection(@gate_class) do |connection|
|
|
245
222
|
begin
|
|
246
223
|
connection.transaction(requires_new: true) do
|
|
247
224
|
@gate_class.create! do |g|
|
|
@@ -297,6 +274,26 @@ module Flipper
|
|
|
297
274
|
model.connection_pool.with_connection(&block)
|
|
298
275
|
end
|
|
299
276
|
|
|
277
|
+
def with_write_connection(model = @feature_class, &block)
|
|
278
|
+
# Use Rails' built-in method to find the class that controls the connection
|
|
279
|
+
# This walks up the inheritance chain to find which class called connects_to
|
|
280
|
+
if model.respond_to?(:connection_class_for_self)
|
|
281
|
+
connection_class = model.connection_class_for_self
|
|
282
|
+
|
|
283
|
+
# Only use connected_to if this class actually has connects_to configured
|
|
284
|
+
# connection_class? returns true when connects_to was called on the class
|
|
285
|
+
if connection_class.respond_to?(:connection_class?) && connection_class.connection_class?
|
|
286
|
+
connection_class.connected_to(role: :writing) do
|
|
287
|
+
with_connection(model, &block)
|
|
288
|
+
end
|
|
289
|
+
else
|
|
290
|
+
with_connection(model, &block)
|
|
291
|
+
end
|
|
292
|
+
else
|
|
293
|
+
with_connection(model, &block)
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
|
|
300
297
|
def warned_about_value_not_text?
|
|
301
298
|
return @warned_about_value_not_text if defined?(@warned_about_value_not_text)
|
|
302
299
|
@warned_about_value_not_text = true
|
data/lib/flipper/version.rb
CHANGED
|
@@ -94,36 +94,36 @@ RSpec.describe Flipper::Adapters::ActiveRecord do
|
|
|
94
94
|
|
|
95
95
|
context "ActiveRecord connection_pool" do
|
|
96
96
|
before do
|
|
97
|
-
|
|
97
|
+
clear_active_connections!
|
|
98
98
|
end
|
|
99
99
|
|
|
100
100
|
context "#features" do
|
|
101
101
|
it "does not hold onto connections" do
|
|
102
|
-
expect(
|
|
102
|
+
expect(active_connections?).to be(false)
|
|
103
103
|
subject.features
|
|
104
|
-
expect(
|
|
104
|
+
expect(active_connections?).to be(false)
|
|
105
105
|
end
|
|
106
106
|
|
|
107
107
|
it "does not release previously held connection" do
|
|
108
108
|
ActiveRecord::Base.connection # establish a new connection
|
|
109
|
-
expect(
|
|
109
|
+
expect(active_connections?).to be(true)
|
|
110
110
|
subject.features
|
|
111
|
-
expect(
|
|
111
|
+
expect(active_connections?).to be(true)
|
|
112
112
|
end
|
|
113
113
|
end
|
|
114
114
|
|
|
115
115
|
context "#get_all" do
|
|
116
116
|
it "does not hold onto connections" do
|
|
117
|
-
expect(
|
|
117
|
+
expect(active_connections?).to be(false)
|
|
118
118
|
subject.get_all
|
|
119
|
-
expect(
|
|
119
|
+
expect(active_connections?).to be(false)
|
|
120
120
|
end
|
|
121
121
|
|
|
122
122
|
it "does not release previously held connection" do
|
|
123
123
|
ActiveRecord::Base.connection # establish a new connection
|
|
124
|
-
expect(
|
|
124
|
+
expect(active_connections?).to be(true)
|
|
125
125
|
subject.get_all
|
|
126
|
-
expect(
|
|
126
|
+
expect(active_connections?).to be(true)
|
|
127
127
|
end
|
|
128
128
|
end
|
|
129
129
|
|
|
@@ -131,24 +131,24 @@ RSpec.describe Flipper::Adapters::ActiveRecord do
|
|
|
131
131
|
let(:feature) { Flipper::Feature.new(:search, subject) }
|
|
132
132
|
|
|
133
133
|
it "does not hold onto connections" do
|
|
134
|
-
expect(
|
|
134
|
+
expect(active_connections?).to be(false)
|
|
135
135
|
subject.add(feature)
|
|
136
|
-
expect(
|
|
136
|
+
expect(active_connections?).to be(false)
|
|
137
137
|
subject.remove(feature)
|
|
138
|
-
expect(
|
|
138
|
+
expect(active_connections?).to be(false)
|
|
139
139
|
subject.clear(feature)
|
|
140
|
-
expect(
|
|
140
|
+
expect(active_connections?).to be(false)
|
|
141
141
|
end
|
|
142
142
|
|
|
143
143
|
it "does not release previously held connection" do
|
|
144
144
|
ActiveRecord::Base.connection # establish a new connection
|
|
145
|
-
expect(
|
|
145
|
+
expect(active_connections?).to be(true)
|
|
146
146
|
subject.add(feature)
|
|
147
|
-
expect(
|
|
147
|
+
expect(active_connections?).to be(true)
|
|
148
148
|
subject.remove(feature)
|
|
149
|
-
expect(
|
|
149
|
+
expect(active_connections?).to be(true)
|
|
150
150
|
subject.clear(feature)
|
|
151
|
-
expect(
|
|
151
|
+
expect(active_connections?).to be(true)
|
|
152
152
|
end
|
|
153
153
|
end
|
|
154
154
|
|
|
@@ -156,16 +156,16 @@ RSpec.describe Flipper::Adapters::ActiveRecord do
|
|
|
156
156
|
let(:feature) { Flipper::Feature.new(:search, subject) }
|
|
157
157
|
|
|
158
158
|
it "does not hold onto connections" do
|
|
159
|
-
expect(
|
|
159
|
+
expect(active_connections?).to be(false)
|
|
160
160
|
subject.get_multi([feature])
|
|
161
|
-
expect(
|
|
161
|
+
expect(active_connections?).to be(false)
|
|
162
162
|
end
|
|
163
163
|
|
|
164
164
|
it "does not release previously held connection" do
|
|
165
165
|
ActiveRecord::Base.connection # establish a new connection
|
|
166
|
-
expect(
|
|
166
|
+
expect(active_connections?).to be(true)
|
|
167
167
|
subject.get_multi([feature])
|
|
168
|
-
expect(
|
|
168
|
+
expect(active_connections?).to be(true)
|
|
169
169
|
end
|
|
170
170
|
end
|
|
171
171
|
|
|
@@ -174,20 +174,20 @@ RSpec.describe Flipper::Adapters::ActiveRecord do
|
|
|
174
174
|
let(:gate) { feature.gate(:boolean)}
|
|
175
175
|
|
|
176
176
|
it "does not hold onto connections" do
|
|
177
|
-
expect(
|
|
177
|
+
expect(active_connections?).to be(false)
|
|
178
178
|
subject.enable(feature, gate, gate.wrap(true))
|
|
179
|
-
expect(
|
|
179
|
+
expect(active_connections?).to be(false)
|
|
180
180
|
subject.disable(feature, gate, gate.wrap(false))
|
|
181
|
-
expect(
|
|
181
|
+
expect(active_connections?).to be(false)
|
|
182
182
|
end
|
|
183
183
|
|
|
184
184
|
it "does not release previously held connection" do
|
|
185
185
|
ActiveRecord::Base.connection # establish a new connection
|
|
186
|
-
expect(
|
|
186
|
+
expect(active_connections?).to be(true)
|
|
187
187
|
subject.enable(feature, gate, gate.wrap(true))
|
|
188
|
-
expect(
|
|
188
|
+
expect(active_connections?).to be(true)
|
|
189
189
|
subject.disable(feature, gate, gate.wrap(false))
|
|
190
|
-
expect(
|
|
190
|
+
expect(active_connections?).to be(true)
|
|
191
191
|
end
|
|
192
192
|
end
|
|
193
193
|
|
|
@@ -196,20 +196,118 @@ RSpec.describe Flipper::Adapters::ActiveRecord do
|
|
|
196
196
|
let(:gate) { feature.gate(:group) }
|
|
197
197
|
|
|
198
198
|
it "does not hold onto connections" do
|
|
199
|
-
expect(
|
|
199
|
+
expect(active_connections?).to be(false)
|
|
200
200
|
subject.enable(feature, gate, gate.wrap(:admin))
|
|
201
|
-
expect(
|
|
201
|
+
expect(active_connections?).to be(false)
|
|
202
202
|
subject.disable(feature, gate, gate.wrap(:admin))
|
|
203
|
-
expect(
|
|
203
|
+
expect(active_connections?).to be(false)
|
|
204
204
|
end
|
|
205
205
|
|
|
206
206
|
it "does not release previously held connection" do
|
|
207
207
|
ActiveRecord::Base.connection # establish a new connection
|
|
208
|
-
expect(
|
|
208
|
+
expect(active_connections?).to be(true)
|
|
209
209
|
subject.enable(feature, gate, gate.wrap(:admin))
|
|
210
|
-
expect(
|
|
210
|
+
expect(active_connections?).to be(true)
|
|
211
211
|
subject.disable(feature, gate, gate.wrap(:admin))
|
|
212
|
-
expect(
|
|
212
|
+
expect(active_connections?).to be(true)
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
if ActiveRecord.version >= Gem::Version.new('7.1')
|
|
218
|
+
context 'with read/write roles' do
|
|
219
|
+
before do
|
|
220
|
+
skip "connected_to with roles is not supported on #{config['adapter']}" if config["adapter"] == "sqlite3"
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
let(:abstract_class) do
|
|
224
|
+
# Create a named abstract class (Rails requires names for connects_to)
|
|
225
|
+
klass = Class.new(ActiveRecord::Base) do
|
|
226
|
+
self.abstract_class = true
|
|
227
|
+
end
|
|
228
|
+
stub_const('TestApplicationRecord', klass)
|
|
229
|
+
|
|
230
|
+
# Now configure connects_to with the same database for both roles
|
|
231
|
+
# In production, these would be different (primary/replica)
|
|
232
|
+
klass.connects_to database: {
|
|
233
|
+
writing: config,
|
|
234
|
+
reading: config
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
klass
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
after do
|
|
241
|
+
# Disconnect role-based connections to avoid interfering with database cleanup
|
|
242
|
+
clear_all_connections!
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
let(:feature_class) do
|
|
246
|
+
klass = Class.new(abstract_class) do
|
|
247
|
+
self.table_name = 'flipper_features'
|
|
248
|
+
validates :key, presence: true
|
|
249
|
+
end
|
|
250
|
+
stub_const('TestFeature', klass)
|
|
251
|
+
klass
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
let(:gate_class) do
|
|
255
|
+
klass = Class.new(abstract_class) do
|
|
256
|
+
self.table_name = 'flipper_gates'
|
|
257
|
+
end
|
|
258
|
+
stub_const('TestGate', klass)
|
|
259
|
+
klass
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
let(:adapter_with_roles) do
|
|
263
|
+
described_class.new(
|
|
264
|
+
feature_class: feature_class,
|
|
265
|
+
gate_class: gate_class
|
|
266
|
+
)
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
it 'can perform write operations when forced to reading role' do
|
|
270
|
+
abstract_class.connected_to(role: :reading) do
|
|
271
|
+
flipper = Flipper.new(adapter_with_roles)
|
|
272
|
+
|
|
273
|
+
feature = flipper[:test_feature]
|
|
274
|
+
expect { feature.enable }.not_to raise_error
|
|
275
|
+
expect(feature.enabled?).to be(true)
|
|
276
|
+
expect { feature.disable }.not_to raise_error
|
|
277
|
+
expect(feature.enabled?).to be(false)
|
|
278
|
+
|
|
279
|
+
feature = flipper[:actor_test]
|
|
280
|
+
actor = Struct.new(:flipper_id).new(123)
|
|
281
|
+
expect { feature.enable_actor(actor) }.not_to raise_error
|
|
282
|
+
expect(feature.enabled?(actor)).to be(true)
|
|
283
|
+
expect { feature.disable_actor(actor) }.not_to raise_error
|
|
284
|
+
expect(feature.enabled?(actor)).to be(false)
|
|
285
|
+
|
|
286
|
+
feature = flipper[:gate_test]
|
|
287
|
+
expect { feature.enable_percentage_of_time(50) }.not_to raise_error
|
|
288
|
+
expect { feature.disable_percentage_of_time }.not_to raise_error
|
|
289
|
+
feature.enable
|
|
290
|
+
expect { feature.remove }.not_to raise_error
|
|
291
|
+
|
|
292
|
+
feature = flipper[:expression_test]
|
|
293
|
+
expression = Flipper.property(:plan).eq("premium")
|
|
294
|
+
expect { feature.enable_expression(expression) }.not_to raise_error
|
|
295
|
+
expect(feature.expression).to eq(expression)
|
|
296
|
+
expect { feature.disable_expression }.not_to raise_error
|
|
297
|
+
expect(feature.expression).to be_nil
|
|
298
|
+
end
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
it 'does not hold onto connections during write operations' do
|
|
302
|
+
clear_active_connections!
|
|
303
|
+
|
|
304
|
+
abstract_class.connected_to(role: :reading) do
|
|
305
|
+
flipper = Flipper.new(adapter_with_roles)
|
|
306
|
+
feature = flipper[:connection_test]
|
|
307
|
+
|
|
308
|
+
feature.enable
|
|
309
|
+
expect(active_connections?).to be(false)
|
|
310
|
+
end
|
|
213
311
|
end
|
|
214
312
|
end
|
|
215
313
|
end
|
|
@@ -265,4 +363,19 @@ RSpec.describe Flipper::Adapters::ActiveRecord do
|
|
|
265
363
|
end
|
|
266
364
|
end
|
|
267
365
|
end
|
|
366
|
+
|
|
367
|
+
def active_connections?
|
|
368
|
+
method = ActiveRecord::Base.connection_handler.method(:active_connections?)
|
|
369
|
+
method.arity == 0 ? method.call : method.call(:all)
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
def clear_active_connections!
|
|
373
|
+
method = ActiveRecord::Base.connection_handler.method(:clear_active_connections!)
|
|
374
|
+
method.arity == 0 ? method.call : method.call(:all)
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
def clear_all_connections!
|
|
378
|
+
method = ActiveRecord::Base.connection_handler.method(:clear_all_connections!)
|
|
379
|
+
method.arity == 0 ? method.call : method.call(:all)
|
|
380
|
+
end
|
|
268
381
|
end
|
|
@@ -47,8 +47,16 @@ class ActiveRecordTest < MiniTest::Test
|
|
|
47
47
|
ActiveRecord::Base.table_name_prefix = :foo_
|
|
48
48
|
ActiveRecord::Base.table_name_suffix = :_bar
|
|
49
49
|
|
|
50
|
+
# Remove constants so they get redefined with new prefix/suffix
|
|
51
|
+
Flipper::Adapters::ActiveRecord.send(:remove_const, :Model) if Flipper::Adapters::ActiveRecord.const_defined?(:Model)
|
|
52
|
+
Flipper::Adapters::ActiveRecord.send(:remove_const, :Feature) if Flipper::Adapters::ActiveRecord.const_defined?(:Feature)
|
|
53
|
+
Flipper::Adapters::ActiveRecord.send(:remove_const, :Gate) if Flipper::Adapters::ActiveRecord.const_defined?(:Gate)
|
|
50
54
|
Flipper::Adapters.send(:remove_const, :ActiveRecord)
|
|
55
|
+
|
|
51
56
|
load("flipper/adapters/active_record.rb")
|
|
57
|
+
load("flipper/adapters/active_record/model.rb")
|
|
58
|
+
load("flipper/adapters/active_record/feature.rb")
|
|
59
|
+
load("flipper/adapters/active_record/gate.rb")
|
|
52
60
|
|
|
53
61
|
assert_equal "foo_flipper_features_bar", Flipper::Adapters::ActiveRecord::Feature.table_name
|
|
54
62
|
assert_equal "foo_flipper_gates_bar", Flipper::Adapters::ActiveRecord::Gate.table_name
|
|
@@ -57,7 +65,15 @@ class ActiveRecordTest < MiniTest::Test
|
|
|
57
65
|
ActiveRecord::Base.table_name_prefix = ""
|
|
58
66
|
ActiveRecord::Base.table_name_suffix = ""
|
|
59
67
|
|
|
68
|
+
# Remove constants so they get redefined with reset prefix/suffix
|
|
69
|
+
Flipper::Adapters::ActiveRecord.send(:remove_const, :Model) if Flipper::Adapters::ActiveRecord.const_defined?(:Model)
|
|
70
|
+
Flipper::Adapters::ActiveRecord.send(:remove_const, :Feature) if Flipper::Adapters::ActiveRecord.const_defined?(:Feature)
|
|
71
|
+
Flipper::Adapters::ActiveRecord.send(:remove_const, :Gate) if Flipper::Adapters::ActiveRecord.const_defined?(:Gate)
|
|
60
72
|
Flipper::Adapters.send(:remove_const, :ActiveRecord)
|
|
73
|
+
|
|
61
74
|
load("flipper/adapters/active_record.rb")
|
|
75
|
+
load("flipper/adapters/active_record/model.rb")
|
|
76
|
+
load("flipper/adapters/active_record/feature.rb")
|
|
77
|
+
load("flipper/adapters/active_record/gate.rb")
|
|
62
78
|
end
|
|
63
79
|
end
|
metadata
CHANGED
|
@@ -1,13 +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.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- John Nunemaker
|
|
8
|
+
autorequire:
|
|
8
9
|
bindir: bin
|
|
9
10
|
cert_chain: []
|
|
10
|
-
date:
|
|
11
|
+
date: 2026-02-26 00:00:00.000000000 Z
|
|
11
12
|
dependencies:
|
|
12
13
|
- !ruby/object:Gem::Dependency
|
|
13
14
|
name: flipper
|
|
@@ -15,14 +16,14 @@ dependencies:
|
|
|
15
16
|
requirements:
|
|
16
17
|
- - "~>"
|
|
17
18
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 1.
|
|
19
|
+
version: 1.4.0
|
|
19
20
|
type: :runtime
|
|
20
21
|
prerelease: false
|
|
21
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
23
|
requirements:
|
|
23
24
|
- - "~>"
|
|
24
25
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: 1.
|
|
26
|
+
version: 1.4.0
|
|
26
27
|
- !ruby/object:Gem::Dependency
|
|
27
28
|
name: activerecord
|
|
28
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -43,6 +44,7 @@ dependencies:
|
|
|
43
44
|
- - "<"
|
|
44
45
|
- !ruby/object:Gem::Version
|
|
45
46
|
version: '9'
|
|
47
|
+
description:
|
|
46
48
|
email: support@flippercloud.io
|
|
47
49
|
executables: []
|
|
48
50
|
extensions: []
|
|
@@ -59,6 +61,9 @@ files:
|
|
|
59
61
|
- flipper-active_record.gemspec
|
|
60
62
|
- lib/flipper-active_record.rb
|
|
61
63
|
- lib/flipper/adapters/active_record.rb
|
|
64
|
+
- lib/flipper/adapters/active_record/feature.rb
|
|
65
|
+
- lib/flipper/adapters/active_record/gate.rb
|
|
66
|
+
- lib/flipper/adapters/active_record/model.rb
|
|
62
67
|
- lib/flipper/version.rb
|
|
63
68
|
- lib/generators/flipper/active_record_generator.rb
|
|
64
69
|
- lib/generators/flipper/templates/migration.erb
|
|
@@ -73,8 +78,9 @@ metadata:
|
|
|
73
78
|
homepage_uri: https://www.flippercloud.io
|
|
74
79
|
source_code_uri: https://github.com/flippercloud/flipper
|
|
75
80
|
bug_tracker_uri: https://github.com/flippercloud/flipper/issues
|
|
76
|
-
changelog_uri: https://github.com/flippercloud/flipper/releases/tag/v1.
|
|
81
|
+
changelog_uri: https://github.com/flippercloud/flipper/releases/tag/v1.4.0
|
|
77
82
|
funding_uri: https://github.com/sponsors/flippercloud
|
|
83
|
+
post_install_message:
|
|
78
84
|
rdoc_options: []
|
|
79
85
|
require_paths:
|
|
80
86
|
- lib
|
|
@@ -89,9 +95,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
89
95
|
- !ruby/object:Gem::Version
|
|
90
96
|
version: '0'
|
|
91
97
|
requirements: []
|
|
92
|
-
rubygems_version: 3.
|
|
98
|
+
rubygems_version: 3.5.22
|
|
99
|
+
signing_key:
|
|
93
100
|
specification_version: 4
|
|
94
101
|
summary: ActiveRecord feature flag adapter for Flipper
|
|
95
|
-
test_files:
|
|
96
|
-
- spec/flipper/adapters/active_record_spec.rb
|
|
97
|
-
- test/adapters/active_record_test.rb
|
|
102
|
+
test_files: []
|