Skip to content

Commit 0f5250a

Browse files
committed
fix: sdk-uses-new-engine-methods
1 parent af51bf7 commit 0f5250a

File tree

9 files changed

+82
-92
lines changed

9 files changed

+82
-92
lines changed

lib/flagsmith.rb

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -217,15 +217,40 @@ def get_identity_segments(identifier, traits = {})
217217
end
218218

219219
identity_model = get_identity_model(identifier, traits)
220-
segment_models = engine.get_identity_segments(environment, identity_model)
221-
segment_models.map { |sm| Flagsmith::Segments::Segment.new(id: sm.id, name: sm.name) }.compact
220+
221+
context = Flagsmith::Engine::EvaluationContext::Mappers.get_evaluation_context(
222+
environment, identity_model
223+
)
224+
225+
unless context
226+
raise Flagsmith::ClientError,
227+
'Local evaluation required to obtain identity segments'
228+
end
229+
230+
evaluation_result = Flagsmith::Engine::Evaluation::Core.get_evaluation_result(context)
231+
232+
evaluation_result[:segments].map do |segment_result|
233+
flagsmith_id = segment_result.dig(:metadata, :flagsmith_id)
234+
next unless flagsmith_id
235+
236+
Flagsmith::Segments::Segment.new(id: flagsmith_id, name: segment_result[:name])
237+
end.compact
222238
end
223239

224240
private
225241

226242
def environment_flags_from_document
227-
Flagsmith::Flags::Collection.from_feature_state_models(
228-
engine.get_environment_feature_states(environment),
243+
context = Flagsmith::Engine::EvaluationContext::Mappers.get_evaluation_context(environment)
244+
245+
unless context
246+
raise Flagsmith::ClientError,
247+
'Unable to get flags. No environment present.'
248+
end
249+
250+
evaluation_result = Flagsmith::Engine::Evaluation::Core.get_evaluation_result(context)
251+
252+
Flagsmith::Flags::Collection.from_evaluation_result(
253+
evaluation_result,
229254
analytics_processor: analytics_processor,
230255
default_flag_handler: default_flag_handler,
231256
offline_handler: offline_handler
@@ -235,9 +260,19 @@ def environment_flags_from_document
235260
def get_identity_flags_from_document(identifier, traits = {})
236261
identity_model = get_identity_model(identifier, traits)
237262

238-
Flagsmith::Flags::Collection.from_feature_state_models(
239-
engine.get_identity_feature_states(environment, identity_model),
240-
identity_id: identity_model.composite_key,
263+
context = Flagsmith::Engine::EvaluationContext::Mappers.get_evaluation_context(
264+
environment, identity_model
265+
)
266+
267+
unless context
268+
raise Flagsmith::ClientError,
269+
'Unable to get flags. No environment present.'
270+
end
271+
272+
evaluation_result = Flagsmith::Engine::Evaluation::Core.get_evaluation_result(context)
273+
274+
Flagsmith::Flags::Collection.from_evaluation_result(
275+
evaluation_result,
241276
analytics_processor: analytics_processor,
242277
default_flag_handler: default_flag_handler,
243278
offline_handler: offline_handler

lib/flagsmith/engine/core.rb

Lines changed: 3 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -17,74 +17,11 @@
1717
module Flagsmith
1818
module Engine
1919
# Flags engine methods
20+
# NOTE: This class is kept for backwards compatibility but no longer contains
21+
# the old model-based evaluation methods. Use the context-based evaluation
22+
# via Flagsmith::Engine::Evaluation::Core.get_evaluation_result instead.
2023
class Engine
2124
include Flagsmith::Engine::Segments::Evaluator
22-
23-
def get_identity_feature_state(environment, identity, feature_name, override_traits = nil)
24-
feature_states = get_identity_feature_states_dict(environment, identity, override_traits).values
25-
26-
feature_state = feature_states.find { |f| f.feature.name == feature_name }
27-
28-
raise Flagsmith::FeatureStateNotFound, 'Feature State Not Found' if feature_state.nil?
29-
30-
feature_state
31-
end
32-
33-
def get_identity_feature_states(environment, identity, override_traits = nil)
34-
feature_states = get_identity_feature_states_dict(environment, identity, override_traits).values
35-
36-
return feature_states.select(&:enabled?) if environment.project.hide_disabled_flags
37-
38-
feature_states
39-
end
40-
41-
def get_environment_feature_state(environment, feature_name)
42-
features_state = environment.feature_states.find { |f| f.feature.name == feature_name }
43-
44-
raise Flagsmith::FeatureStateNotFound, 'Feature State Not Found' if features_state.nil?
45-
46-
features_state
47-
end
48-
49-
def get_environment_feature_states(environment)
50-
return environment.feature_states.select(&:enabled?) if environment.project.hide_disabled_flags
51-
52-
environment.feature_states
53-
end
54-
55-
private
56-
57-
def get_identity_feature_states_dict(environment, identity, override_traits = nil)
58-
# Get feature states from the environment
59-
feature_states = {}
60-
override = ->(fs) { feature_states[fs.feature.id] = fs }
61-
environment.feature_states.each(&override)
62-
63-
override_by_matching_segments(environment, identity, override_traits) do |fs|
64-
override.call(fs) unless higher_segment_priority?(feature_states, fs)
65-
end
66-
67-
# Override with any feature states defined directly the identity
68-
identity.identity_features.each(&override)
69-
feature_states
70-
end
71-
72-
# Override with any feature states defined by matching segments
73-
def override_by_matching_segments(environment, identity, override_traits)
74-
identity_segments = get_identity_segments(environment, identity, override_traits)
75-
identity_segments.each do |matching_segment|
76-
matching_segment.feature_states.each do |feature_state|
77-
yield feature_state if block_given?
78-
end
79-
end
80-
end
81-
82-
def higher_segment_priority?(collection, feature_state)
83-
collection.key?(feature_state.feature.id) &&
84-
collection[feature_state.feature.id].higher_segment_priority?(
85-
feature_state
86-
)
87-
end
8825
end
8926
end
9027
end

lib/flagsmith/engine/evaluation/core.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def evaluate_segments(evaluation_context)
3333
return [], {}
3434
end
3535

36-
identity_segments = get_identity_segments_from_context(evaluation_context)
36+
identity_segments = get_identity_segments(evaluation_context)
3737

3838
segments = identity_segments.map do |segment|
3939
result = {

lib/flagsmith/engine/segments/evaluator.rb

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ module Evaluator
1313
include Flagsmith::Engine::Segments::Constants
1414
include Flagsmith::Engine::Utils::HashFunc
1515

16-
# Context-based segment evaluation (new approach)
16+
# Context-based segment evaluation
1717
# Returns all segments that the identity belongs to based on segment rules evaluation
1818
#
1919
# @param context [Hash] Evaluation context containing identity and segment definitions
2020
# @return [Array<Hash>] Array of segments that the identity matches
21-
def get_identity_segments_from_context(context)
21+
def get_identity_segments(context)
2222
return [] unless context[:identity] && context[:segments]
2323

2424
matching_segments = context[:segments].values.select do |segment|
@@ -31,13 +31,6 @@ def get_identity_segments_from_context(context)
3131
matching_segments
3232
end
3333

34-
# Model-based segment evaluation (existing approach)
35-
def get_identity_segments(environment, identity, override_traits = nil)
36-
environment.project.segments.select do |s|
37-
evaluate_identity_in_segment(identity, s, override_traits)
38-
end
39-
end
40-
4134
# Evaluates whether a given identity is in the provided segment.
4235
#
4336
# :param identity: identity model object to evaluate

lib/flagsmith/engine/segments/models.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ def match_modulo_value(trait_value)
103103
def match_in_value(trait_value)
104104
return false if trait_value.nil? || trait_value.is_a?(TrueClass) || trait_value.is_a?(FalseClass)
105105

106+
# Floats/doubles are not supported by the engine due to ambiguous serialization across supported platforms. (segments/models_spec.rb)
107+
return false unless trait_value.is_a?(String) || trait_value.is_a?(Integer)
108+
106109
if @value.is_a?(Array)
107110
return @value.include?(trait_value.to_s)
108111
end

lib/flagsmith/sdk/models/flags.rb

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,13 @@ def initialize(enabled:, value:)
3232

3333
# 'live' Flag class as returned by API or local evaluation
3434
class Flag < BaseFlag
35-
attr_reader :feature_name, :feature_id
35+
attr_reader :feature_name, :feature_id, :reason
3636

37-
def initialize(feature_name:, enabled:, value:, feature_id:)
37+
def initialize(feature_name:, enabled:, value:, feature_id:, reason: nil)
3838
super(enabled: enabled, value: value, default: false)
3939
@feature_name = feature_name
4040
@feature_id = feature_id
41+
@reason = reason
4142
end
4243

4344
def <=>(other)
@@ -54,7 +55,8 @@ def to_h
5455
feature_name: feature_name,
5556
value: value,
5657
enabled: enabled,
57-
default: default
58+
default: default,
59+
reason: reason
5860
}
5961
end
6062

@@ -184,6 +186,31 @@ def from_feature_state_models(feature_states, identity_id: nil, **args)
184186
)
185187
end
186188

189+
def from_evaluation_result(evaluation_result, **args)
190+
to_flag_object = lambda { |flag_result, acc|
191+
flagsmith_id = flag_result.dig(:metadata, :flagsmith_id)
192+
193+
if flagsmith_id.nil?
194+
raise Flagsmith::ClientError,
195+
"FlagResult metadata.flagsmith_id is missing for feature \"#{flag_result[:name]}\". " \
196+
"This indicates a bug in the SDK, please report it."
197+
end
198+
199+
acc[normalize_key(flag_result[:name])] = Flagsmith::Flags::Flag.new(
200+
feature_name: flag_result[:name],
201+
enabled: flag_result[:enabled],
202+
value: flag_result[:value],
203+
feature_id: flagsmith_id,
204+
reason: flag_result[:reason]
205+
)
206+
}
207+
208+
new(
209+
evaluation_result[:flags].each_value.each_with_object({}, &to_flag_object),
210+
**args
211+
)
212+
end
213+
187214
def normalize_key(key)
188215
key.to_s.downcase
189216
end

spec/engine/e2e/engine_spec.rb

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ def get_test_files
88
end
99

1010
def parse_jsonc(content)
11-
# Simple JSONC parser: remove single-line comments
12-
# JSON.parse will handle the rest
1311
cleaned = content.lines.reject { |line| line.strip.start_with?('//') }.join
1412
JSON.parse(cleaned, symbolize_names: true)
1513
end
@@ -34,11 +32,8 @@ def load_test_file(filepath)
3432
test_evaluation_context = test_case[:context]
3533
test_expected_result = test_case[:result]
3634

37-
# TODO: Implement evaluation logic
3835
evaluation_result = Flagsmith::Engine::Evaluation::Core.get_evaluation_result(test_evaluation_context)
3936

40-
41-
# TODO: Uncomment when evaluation is implemented
4237
expect(evaluation_result[:flags]).to eq(test_expected_result[:flags])
4338
expect(evaluation_result[:segments]).to eq(test_expected_result[:segments])
4439
end
File renamed without changes.

0 commit comments

Comments
 (0)