@@ -41,7 +41,7 @@ def features
4141
4242 # Public: Adds a feature to the set of known features.
4343 def add ( feature )
44- with_connection ( @feature_class ) do
44+ with_write_connection ( @feature_class ) do
4545 @feature_class . transaction ( requires_new : true ) do
4646 begin
4747 # race condition, but add is only used by enable/disable which happen
@@ -60,7 +60,7 @@ def add(feature)
6060
6161 # Public: Removes a feature from the set of known features.
6262 def remove ( feature )
63- with_connection ( @feature_class ) do
63+ with_write_connection ( @feature_class ) do
6464 @feature_class . transaction do
6565 @feature_class . where ( key : feature . key ) . destroy_all
6666 clear ( feature )
@@ -71,7 +71,7 @@ def remove(feature)
7171
7272 # Public: Clears the gate values for a feature.
7373 def clear ( feature )
74- with_connection ( @gate_class ) { @gate_class . where ( feature_key : feature . key ) . destroy_all }
74+ with_write_connection ( @gate_class ) { @gate_class . where ( feature_key : feature . key ) . destroy_all }
7575 true
7676 end
7777
@@ -165,9 +165,11 @@ def disable(feature, gate, thing)
165165 when :integer
166166 set ( feature , gate , thing )
167167 when :json
168- delete ( feature , gate )
168+ with_write_connection ( @gate_class ) do
169+ delete ( feature , gate )
170+ end
169171 when :set
170- with_connection ( @gate_class ) do
172+ with_write_connection ( @gate_class ) do
171173 @gate_class . where ( feature_key : feature . key , key : gate . key , value : thing . value ) . destroy_all
172174 end
173175 else
@@ -190,7 +192,7 @@ def set(feature, gate, thing, options = {})
190192
191193 raise VALUE_TO_TEXT_WARNING if json_feature && value_not_text?
192194
193- with_connection ( @gate_class ) do
195+ with_write_connection ( @gate_class ) do
194196 @gate_class . transaction ( requires_new : true ) do
195197 clear ( feature ) if clear_feature
196198 delete ( feature , gate )
@@ -215,7 +217,7 @@ def delete(feature, gate)
215217 end
216218
217219 def enable_multi ( feature , gate , thing )
218- with_connection ( @gate_class ) do |connection |
220+ with_write_connection ( @gate_class ) do |connection |
219221 begin
220222 connection . transaction ( requires_new : true ) do
221223 @gate_class . create! do |g |
@@ -271,6 +273,34 @@ def with_connection(model = @feature_class, &block)
271273 model . connection_pool . with_connection ( &block )
272274 end
273275
276+ def with_write_connection ( model = @feature_class , &block )
277+ warn VALUE_TO_TEXT_WARNING if !warned_about_value_not_text? && value_not_text?
278+
279+ # Use connected_to for role switching if available (Rails 6.1+)
280+ # This ensures writes go to primary/write database when using read/write roles
281+ if model . respond_to? ( :connected_to )
282+ begin
283+ # Find the abstract class that manages the connection
284+ # Walk up the inheritance chain to find it
285+ connection_class = model
286+ until connection_class . abstract_class? || connection_class == ::ActiveRecord ::Base
287+ connection_class = connection_class . superclass
288+ break if connection_class == ::ActiveRecord ::Base || !connection_class . respond_to? ( :abstract_class? )
289+ end
290+
291+ connection_class . connected_to ( role : :writing ) do
292+ model . connection_pool . with_connection ( &block )
293+ end
294+ rescue NotImplementedError
295+ # connected_to not available or not configured for roles, fall back
296+ model . connection_pool . with_connection ( &block )
297+ end
298+ else
299+ # Fall back to regular connection for single database or older Rails
300+ model . connection_pool . with_connection ( &block )
301+ end
302+ end
303+
274304 def warned_about_value_not_text?
275305 return @warned_about_value_not_text if defined? ( @warned_about_value_not_text )
276306 @warned_about_value_not_text = true
0 commit comments