magick-feature-flags 1.4.1 → 1.4.2

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: 3df9cccb3e3478e71402fa478d4a70401d0150290fdca89a6a47df7fbd901794
4
- data.tar.gz: 929990ca6220cebb2e9215a1993df11fa25a71dbf620029a176db1c8b50edf48
3
+ metadata.gz: ce69954c64fae4d8ec9d10d177621ef508c1f0d8db98b9012849250d90cc974f
4
+ data.tar.gz: 41024341850d984dc1b16c8e85913160a94eb92b96f5eaf07477d9ff93a46de4
5
5
  SHA512:
6
- metadata.gz: 225fdbbed5820df1ca9cb7f0283172b57ab5a3c0a26639fc6d11cef9553f80cc35402753878469db7470ef90ac691431daf399cac1b1cba26d23395ce5776f8c
7
- data.tar.gz: da03312e98129cc04bc0ba63dfc06e67e171406e35fa4e46f9ff73c494a0596ef4e1e65868bab0a0ad7f43f05bbf449a81d9ac1b25eae5a0d40e1ba6245f4e44
6
+ metadata.gz: a16aa4722424020d4d4ab0d45c1dc5bfec6452ae6f24177d713e6f98790d33b4851bb340e39603aecf52c06bf2d669d0876c0b3835bc9ebf4f63cd92e7776ccc
7
+ data.tar.gz: 3a49561daaf30a060abefd7c11413dd5e87e27771b59e089d287cb2788920f5f9c334c4922e064d03c18ce692b6f37a6bfeaf419f09ba12891313c3be1eb1f8a
@@ -87,11 +87,8 @@ module Magick
87
87
  end
88
88
 
89
89
  def enable
90
- if @feature.enable
91
- redirect_to magick_admin_ui.features_path, notice: 'Feature enabled'
92
- else
93
- redirect_to magick_admin_ui.feature_path(@feature.name), alert: 'Cannot enable feature — its dependencies must be enabled first'
94
- end
90
+ @feature.enable
91
+ redirect_to magick_admin_ui.features_path, notice: 'Feature enabled'
95
92
  end
96
93
 
97
94
  def disable
@@ -107,6 +107,11 @@ module Magick
107
107
  return false if status == :inactive
108
108
  return false if status == :deprecated && !context[:allow_deprecated]
109
109
 
110
+ # Dependency check: a feature with unmet prerequisites evaluates as disabled,
111
+ # regardless of its own configured state. Evaluation-only — prerequisite state
112
+ # is never written into this feature.
113
+ return false unless dependencies_satisfied?(context)
114
+
110
115
  # Fast path: skip targeting checks if targeting is empty (most common case)
111
116
  unless @_targeting_empty
112
117
  # Check exclusions FIRST — exclusions always take priority over inclusions
@@ -532,18 +537,6 @@ module Magick
532
537
  end
533
538
 
534
539
  def enable(user_id: nil)
535
- # Check that all of this feature's own dependencies are enabled
536
- # e.g. if checkout depends on payments, checkout can't be enabled until payments is
537
- deps = @dependencies || []
538
- unless deps.empty?
539
- disabled_deps = deps.select do |dep_name|
540
- dep_feature = Magick.features[dep_name.to_s] || Magick[dep_name]
541
- dep_feature && !dep_feature.enabled?
542
- end
543
-
544
- return false unless disabled_deps.empty?
545
- end
546
-
547
540
  # Clear all targeting to enable globally
548
541
  @targeting = {}
549
542
  save_targeting
@@ -589,9 +582,6 @@ module Magick
589
582
  registered.instance_variable_set(:@targeting, {})
590
583
  end
591
584
 
592
- # Cascade disable: disable all features that depend on this one
593
- disable_dependent_features(user_id: user_id)
594
-
595
585
  # Rails 8+ event
596
586
  if defined?(Magick::Rails::Events) && Magick::Rails::Events.rails8?
597
587
  Magick::Rails::Events.feature_disabled_globally(name, user_id: user_id)
@@ -1015,42 +1005,18 @@ module Magick
1015
1005
  context
1016
1006
  end
1017
1007
 
1018
- def disable_dependent_features(user_id: nil)
1019
- # Cascade-disable features that depend ON this feature.
1020
- # e.g. if checkout depends on payments, disabling payments also disables checkout.
1021
- dependents = find_dependent_features
1022
- return if dependents.empty?
1023
-
1024
- dependents.each do |dep_name|
1025
- dep_feature = Magick.features[dep_name.to_s] || Magick[dep_name]
1026
- next unless dep_feature
1008
+ def dependencies_satisfied?(context)
1009
+ deps = @dependencies
1010
+ return true if deps.nil? || deps.empty?
1027
1011
 
1028
- dep_feature.instance_variable_set(:@targeting, {})
1029
- dep_feature.save_targeting
1030
-
1031
- case dep_feature.type
1032
- when :boolean
1033
- dep_feature.set_value(false, user_id: user_id)
1034
- when :string
1035
- dep_feature.set_value('', user_id: user_id)
1036
- when :number
1037
- dep_feature.set_value(0, user_id: user_id)
1038
- end
1039
-
1040
- if defined?(Magick::Rails::Events) && Magick::Rails::Events.rails8?
1041
- Magick::Rails::Events.feature_disabled_globally(dep_name, user_id: user_id)
1042
- end
1043
- end
1044
- end
1012
+ deps.all? do |dep_name|
1013
+ dep_feature = Magick.features[dep_name.to_s] || Magick.features[dep_name.to_sym]
1014
+ # Unknown dependency is treated as satisfied — matches prior behavior
1015
+ # where missing features were skipped in cascade logic.
1016
+ next true unless dep_feature
1045
1017
 
1046
- def find_dependent_features
1047
- # Find all features that have this feature in their dependencies
1048
- dependent_features = []
1049
- Magick.features.each do |_name, feature|
1050
- feature_deps = feature.instance_variable_get(:@dependencies) || []
1051
- dependent_features << feature.name if feature_deps.include?(name.to_s) || feature_deps.include?(name.to_sym)
1018
+ dep_feature.enabled?(context)
1052
1019
  end
1053
- dependent_features
1054
1020
  end
1055
1021
 
1056
1022
  def excluded?(context)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Magick
4
- VERSION = '1.4.1'
4
+ VERSION = '1.4.2'
5
5
  end
data/lib/magick.rb CHANGED
@@ -31,7 +31,6 @@ require_relative 'magick/export_import'
31
31
  require_relative 'magick/versioning'
32
32
  require_relative 'magick/circuit_breaker'
33
33
  require_relative 'magick/testing_helpers'
34
- require_relative 'magick/feature_dependency'
35
34
  require_relative 'magick/documentation'
36
35
  # AdminUI is loaded conditionally via configuration
37
36
  # It is not loaded by default - must be enabled in Magick.configure
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: magick-feature-flags
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.1
4
+ version: 1.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Lobanov
@@ -128,7 +128,6 @@ files:
128
128
  - lib/magick/errors.rb
129
129
  - lib/magick/export_import.rb
130
130
  - lib/magick/feature.rb
131
- - lib/magick/feature_dependency.rb
132
131
  - lib/magick/feature_variant.rb
133
132
  - lib/magick/log_safe.rb
134
133
  - lib/magick/performance_metrics.rb
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Magick
4
- class FeatureDependency
5
- def self.check(feature_name, context = {})
6
- feature = Magick.features[feature_name.to_s] || Magick[feature_name]
7
- dependencies = feature.instance_variable_get(:@dependencies) || []
8
-
9
- dependencies.all? do |dep_name|
10
- Magick.enabled?(dep_name, context)
11
- end
12
- end
13
-
14
- def self.add_dependency(feature_name, dependency_name)
15
- feature = Magick.features[feature_name.to_s] || Magick[feature_name]
16
- dependencies = feature.instance_variable_get(:@dependencies) || []
17
- dependencies << dependency_name.to_s unless dependencies.include?(dependency_name.to_s)
18
- feature.instance_variable_set(:@dependencies, dependencies)
19
- end
20
-
21
- def self.remove_dependency(feature_name, dependency_name)
22
- feature = Magick.features[feature_name.to_s] || Magick[feature_name]
23
- dependencies = feature.instance_variable_get(:@dependencies) || []
24
- dependencies.delete(dependency_name.to_s)
25
- feature.instance_variable_set(:@dependencies, dependencies)
26
- end
27
- end
28
- end