Skip to content

Commit c645e79

Browse files
committed
feat: rebased
2 parents 60dfef6 + 6a6a129 commit c645e79

File tree

6 files changed

+41
-56
lines changed

6 files changed

+41
-56
lines changed

lib/flagsmith.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ def get_identity_segments(identifier, traits = {})
218218

219219
identity_model = get_identity_model(identifier, traits)
220220

221-
context = Flagsmith::Engine::EvaluationContext::Mappers.get_evaluation_context(
221+
context = Flagsmith::Engine::Evaluation::Mappers.get_evaluation_context(
222222
environment, identity_model
223223
)
224224

@@ -240,7 +240,7 @@ def get_identity_segments(identifier, traits = {})
240240
private
241241

242242
def environment_flags_from_document
243-
context = Flagsmith::Engine::EvaluationContext::Mappers.get_evaluation_context(environment)
243+
context = Flagsmith::Engine::Evaluation::Mappers.get_evaluation_context(environment)
244244

245245
unless context
246246
raise Flagsmith::ClientError,
@@ -260,7 +260,7 @@ def environment_flags_from_document
260260
def get_identity_flags_from_document(identifier, traits = {})
261261
identity_model = get_identity_model(identifier, traits)
262262

263-
context = Flagsmith::Engine::EvaluationContext::Mappers.get_evaluation_context(
263+
context = Flagsmith::Engine::Evaluation::Mappers.get_evaluation_context(
264264
environment, identity_model
265265
)
266266

lib/flagsmith/engine/evaluation/core.rb

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,13 @@ def get_evaluation_result(evaluation_context)
2323
flags = evaluate_features(evaluation_context, segment_overrides)
2424
{
2525
flags: flags,
26-
segments: segments,
26+
segments: segments
2727
}
2828
end
2929

3030
# Returns { segments: EvaluationResultSegments; segmentOverrides: Record<string, SegmentOverride>; }
3131
def evaluate_segments(evaluation_context)
32-
if evaluation_context[:identity].nil? || evaluation_context[:segments].nil?
33-
return [], {}
34-
end
32+
return [], {} if evaluation_context[:identity].nil? || evaluation_context[:segments].nil?
3533

3634
identity_segments = get_identity_segments(evaluation_context)
3735

@@ -40,16 +38,14 @@ def evaluate_segments(evaluation_context)
4038
name: segment[:name]
4139
}
4240

43-
if segment[:metadata]
44-
result[:metadata] = segment[:metadata].dup
45-
end
41+
result[:metadata] = segment[:metadata].dup if segment[:metadata]
4642

4743
result
4844
end
4945

5046
segment_overrides = process_segment_overrides(identity_segments)
5147

52-
return segments, segment_overrides
48+
[segments, segment_overrides]
5349
end
5450

5551
# Returns Record<string: override.name, SegmentOverride>
@@ -62,12 +58,12 @@ def process_segment_overrides(identity_segments)
6258
overrides_list = segment[:overrides].is_a?(Array) ? segment[:overrides] : []
6359

6460
overrides_list.each do |override|
65-
if should_apply_override(override, segment_overrides)
66-
segment_overrides[override[:name]] = {
67-
feature: override,
68-
segment_name: segment[:name]
69-
}
70-
end
61+
next unless should_apply_override(override, segment_overrides)
62+
63+
segment_overrides[override[:name]] = {
64+
feature: override,
65+
segment_name: segment[:name]
66+
}
7167
end
7268
end
7369

@@ -102,7 +98,7 @@ def evaluate_features(evaluation_context, segment_overrides)
10298

10399
# Set reason
104100
flag_result[:reason] = evaluated[:reason] ||
105-
get_targeting_match_reason({ type: 'SEGMENT', override: segment_override })
101+
get_targeting_match_reason({ type: 'SEGMENT', override: segment_override })
106102

107103
flags[final_feature[:name].to_sym] = flag_result
108104
end
@@ -112,9 +108,7 @@ def evaluate_features(evaluation_context, segment_overrides)
112108

113109
# Returns {value: any; reason?: string}
114110
def evaluate_feature_value(feature, identity_key = nil)
115-
if feature[:variants]&.any? && identity_key
116-
return get_multivariate_feature_value(feature, identity_key)
117-
end
111+
return get_multivariate_feature_value(feature, identity_key) if feature[:variants]&.any? && identity_key
118112

119113
{ value: feature[:value], reason: nil }
120114
end

lib/flagsmith/engine/evaluation/mappers.rb

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
module Flagsmith
44
module Engine
5-
module EvaluationContext
5+
module Evaluation
66
module Mappers
77
STRONGEST_PRIORITY = Float::INFINITY
88
WEAKEST_PRIORITY = -Float::INFINITY
@@ -55,7 +55,8 @@ def self.map_environment_model_to_evaluation_context(environment)
5555
}
5656

5757
feature_hash[:variants] = variants if variants
58-
feature_hash[:priority] = fs.feature_segment.priority if fs.feature_segment&.priority
58+
priority = fs.feature_segment&.priority
59+
feature_hash[:priority] = priority unless priority.nil?
5960
feature_hash[:metadata] = { flagsmith_id: fs.feature.id }
6061

6162
features[fs.feature.name] = feature_hash
@@ -138,17 +139,9 @@ def self.map_segment_rule_model_to_rule(rule)
138139
}
139140

140141
# Map conditions if present
141-
result[:conditions] = if rule.conditions&.any?
142-
rule.conditions.map do |condition|
143-
{
144-
property: condition.property,
145-
operator: condition.operator,
146-
value: condition.value
147-
}
148-
end
149-
else
150-
[]
151-
end
142+
result[:conditions] = (rule.conditions || []).map do |condition|
143+
{ property: condition.property, operator: condition.operator, value: condition.value }
144+
end
152145

153146
result[:rules] = if rule.rules&.any?
154147
rule.rules.map { |nested_rule| map_segment_rule_model_to_rule(nested_rule) }
@@ -188,7 +181,7 @@ def self.map_identity_overrides_to_segments(identity_overrides)
188181
end
189182

190183
# Create hash of the overrides to group identities with same overrides
191-
overrides_hash = overrides_key.hash
184+
overrides_hash = Digest::SHA1.hexdigest(overrides_key.inspect)
192185

193186
features_to_identifiers[overrides_hash] ||= { identifiers: [], overrides: overrides_key }
194187
features_to_identifiers[overrides_hash][:identifiers] << identity.identifier

lib/flagsmith/engine/segments/evaluator.rb

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,26 +11,24 @@ module Engine
1111
module Segments
1212
# Evaluator methods
1313
module Evaluator
14-
extend self
1514
include Flagsmith::Engine::Segments::Constants
1615
include Flagsmith::Engine::Utils::HashFunc
1716

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

26-
matching_segments = context[:segments].values.select do |segment|
26+
context[:segments].values.select do |segment|
2727
next false if segment[:rules].nil? || segment[:rules].empty?
2828

2929
matches = segment[:rules].all? { |rule| traits_match_segment_rule_from_context(rule, segment[:key], context) }
3030
matches
3131
end
32-
33-
matching_segments
3432
end
3533

3634
# Context-based helper functions
@@ -55,7 +53,7 @@ def traits_match_segment_rule_from_context(rule, segment_key, context)
5553
# @param context [Hash] The evaluation context
5654
# @return [Boolean] True if conditions match according to rule type
5755
def evaluate_conditions_from_context(rule, segment_key, context)
58-
return true if rule[:conditions].nil? || rule[:conditions].empty?
56+
return true unless rule[:conditions]&.any?
5957

6058
condition_results = rule[:conditions].map do |condition|
6159
traits_match_segment_condition_from_context(condition, segment_key, context)
@@ -93,10 +91,10 @@ def traits_match_segment_condition_from_context(condition, segment_key, context)
9391

9492
return false if condition[:property].nil?
9593
trait_value = get_trait_value(condition[:property], context)
96-
return trait_value != nil if condition[:operator] == IS_SET
94+
return !trait_value.nil? if condition[:operator] == IS_SET
9795
return trait_value.nil? if condition[:operator] == IS_NOT_SET
9896

99-
if !trait_value.nil?
97+
unless trait_value.nil?
10098
# Reuse existing Condition class logic
10199
condition_obj = Flagsmith::Engine::Segments::Condition.new(
102100
operator: condition[:operator],
@@ -135,9 +133,7 @@ def evaluate_rule_conditions(rule_type, condition_results)
135133
def get_trait_value(property, context)
136134
if property.start_with?('$.')
137135
context_value = get_context_value(property, context)
138-
if !context_value.nil? && !non_primitive?(context_value)
139-
return context_value
140-
end
136+
return context_value if !context_value.nil? && !non_primitive?(context_value)
141137
end
142138

143139
traits = context.dig(:identity, :traits) || {}

lib/flagsmith/engine/segments/models.rb

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ def match_trait_value?(trait_value)
5858
if @value.is_a?(String) && @value.match?(/:semver$/)
5959
begin
6060
trait_value = Semantic::Version.new(trait_value.to_s.gsub(/:semver$/, ''))
61-
rescue StandardError
61+
rescue ArgumentError, Semantic::Version::ValidationFailed => _e
6262
return false
6363
end
6464
end
@@ -81,12 +81,12 @@ def format_to_type_of(input)
8181
# Double check this is the desired behavior between SDKs
8282
'TrueClass' => ->(v) { ['True', 'true', 'TRUE', true, 1, '1'].include?(v) },
8383
'FalseClass' => ->(v) { !['False', 'false', 'FALSE', false].include?(v) },
84-
'Integer' => ->(v) {
85-
i = v.to_i;
84+
'Integer' => lambda { |v|
85+
i = v.to_i
8686
i.to_s == v.to_s ? i : v
8787
},
88-
'Float' => ->(v) {
89-
f = v.to_f;
88+
'Float' => lambda { |v|
89+
f = v.to_f
9090
f.to_s == v.to_s ? f : v
9191
}
9292
}[input.class.to_s]
@@ -103,19 +103,21 @@ 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+
<<<<<<< HEAD
106107
# Floats/doubles are not supported by the engine due to ambiguous serialization across supported platforms. (segments/models_spec.rb)
107108
return false unless trait_value.is_a?(String) || trait_value.is_a?(Integer)
108109

109110
if @value.is_a?(Array)
110111
return @value.include?(trait_value.to_s)
111112
end
113+
=======
114+
return @value.include?(trait_value.to_s) if @value.is_a?(Array)
115+
>>>>>>> 6a6a129d14a0f15bbf3252a2c6b539681dfa7e85
112116

113117
if @value.is_a?(String)
114118
begin
115119
parsed = JSON.parse(@value)
116-
if parsed.is_a?(Array)
117-
return parsed.include?(trait_value.to_s)
118-
end
120+
return parsed.include?(trait_value.to_s) if parsed.is_a?(Array)
119121
rescue JSON::ParserError
120122
end
121123
end

spec/engine/unit/evaluation_context_mappers_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
require 'spec_helper'
44

5-
RSpec.describe Flagsmith::Engine::EvaluationContext::Mappers do
5+
RSpec.describe Flagsmith::Engine::Evaluation::Mappers do
66
describe '.get_evaluation_context' do
77
let(:environment_json) do
88
JSON.parse(
@@ -72,7 +72,7 @@
7272
expect(override[:name]).to eq('some_feature')
7373
expect(override[:enabled]).to be false
7474
expect(override[:value]).to eq('some-overridden-value')
75-
expect(override[:priority]).to eq(Flagsmith::Engine::EvaluationContext::Mappers::STRONGEST_PRIORITY)
75+
expect(override[:priority]).to eq(Flagsmith::Engine::Evaluation::Mappers::STRONGEST_PRIORITY)
7676
expect(override[:metadata][:flagsmith_id]).to eq(1)
7777

7878
# Verify features

0 commit comments

Comments
 (0)