Skip to content

Commit

Permalink
Adding Custom Field Support
Browse files Browse the repository at this point in the history
  • Loading branch information
hermeswaldemarin committed Nov 14, 2023
1 parent 54cc613 commit 876489c
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 9 deletions.
83 changes: 83 additions & 0 deletions lib/context.rb
Expand Up @@ -21,6 +21,7 @@ def self.create(clock, config, data_future, data_provider,
def initialize(clock, config, data_future, data_provider,
event_handler, event_logger, variable_parser, audience_matcher)
@index = []
@context_custom_fields = {}
@achievements = []
@assignment_cache = {}
@assignments = {}
Expand Down Expand Up @@ -203,6 +204,52 @@ def variable_value(key, default_value)
default_value
end

def custom_field_keys
check_ready?(true)
keys = []

@data.experiments.each do |experiment|
custom_field_values = experiment.custom_field_values
if custom_field_values != nil
custom_field_values.each do |custom_field|
keys.append(custom_field.name)
end
end
end

return keys.sort.uniq
end

def custom_field_value(experimentName, key)
check_ready?(true)

experiment_custom_fields = @context_custom_fields[experimentName]

if experiment_custom_fields != nil
field = experiment_custom_fields[key]
if field != nil
return field.value
end
end

return nil
end

def custom_field_type(experimentName, key)
check_ready?(true)

experiment_custom_fields = @context_custom_fields[experimentName]

if experiment_custom_fields != nil
field = experiment_custom_fields[key]
if field != nil
return field.type
end
end

return nil
end

def peek_variable_value(key, default_value)
check_ready?(true)

Expand Down Expand Up @@ -451,8 +498,11 @@ def assign_data(data)
@data = data
@index = {}
@index_variables = {}

if data && !data.experiments.nil? && !data.experiments.empty?
data.experiments.each do |experiment|
@experimentCustomFieldValues = {}

experiment_variables = ExperimentVariables.new
experiment_variables.data = experiment
experiment_variables.variables ||= []
Expand All @@ -467,7 +517,36 @@ def assign_data(data)
end
end

if !experiment.custom_field_values.nil?
experiment.custom_field_values.each do |custom_field_value|
value = ContextCustomFieldValues.new
value.type = custom_field_value.type

if !custom_field_value.value.nil?
custom_value = custom_field_value.value

if custom_field_value.type.start_with?("json")
value.value = @variable_parser.parse(self, experiment.name, custom_field_value.name, custom_value)

elsif custom_field_value.type.start_with?("boolean")
value.value = custom_value.to_bool

elsif custom_field_value.type.start_with?("number")
value.value = custom_value.to_i

else
value.value = custom_field_value.value
end

@experimentCustomFieldValues[custom_field_value.name] = value

end

end
end

@index[experiment.name] = experiment_variables
@context_custom_fields[experiment.name] = @experimentCustomFieldValues
end
end
end
Expand Down Expand Up @@ -544,5 +623,9 @@ class ExperimentVariables
attr_accessor :data, :variables
end

class ContextCustomFieldValues
attr_accessor :type, :value
end

class IllegalStateException < StandardError
end
13 changes: 10 additions & 3 deletions lib/json/experiment.rb
Expand Up @@ -3,18 +3,23 @@
require_relative "../string"
require_relative "experiment_application"
require_relative "experiment_variant"
require_relative "custom_field_value"

class Experiment
attr_accessor :id, :name, :unit_type, :iteration, :seed_hi, :seed_lo, :split,
:traffic_seed_hi, :traffic_seed_lo, :traffic_split, :full_on_variant,
:applications, :variants, :audience_strict, :audience
:applications, :variants, :audience_strict, :audience, :custom_field_values

def initialize(args = {})
args.each do |name, value|
if name == :applications
@applications = assign_to_klass(ExperimentApplication, value)
elsif name == :variants
@variants = assign_to_klass(ExperimentVariant, value)
elsif name == :customFieldValues
if value != nil
@custom_field_values = assign_to_klass(CustomFieldValue, value)
end
else
self.instance_variable_set("@#{name.to_s.underscore}", value)
end
Expand Down Expand Up @@ -42,7 +47,7 @@ def ==(o)
@unit_type == that.unit_type && @split == that.split &&
@traffic_split == that.traffic_split && @applications == that.applications &&
@variants == that.variants && @audience_strict == that.audience_strict &&
@audience == that.audience
@audience == that.audience && @custom_field_values == that.custom_field_values
end

def hash_code
Expand All @@ -57,7 +62,8 @@ def hash_code
traffic_seed_lo: @traffic_seed_lo,
full_on_variant: @full_on_variant,
audience_strict: @audience_strict,
audience: @audience
audience: @audience,
custom_field_values: @custom_field_values
}
end

Expand All @@ -78,6 +84,7 @@ def to_s
", variants=#{@variants.join}" +
", audienceStrict=#{@audience_strict}" +
", audience='#{@audience}'" +
", custom_field_values='#{@custom_field_values}'" +
"}"
end
end
6 changes: 3 additions & 3 deletions lib/json_expr/expr_evaluator.rb
Expand Up @@ -32,7 +32,7 @@ def evaluate(expr)
def boolean_convert(x)
if x.is_a?(TrueClass) || x.is_a?(FalseClass)
return x
elsif x.is_a?(Numeric) || !(x =~ NUMERIC_REGEX).nil?
elsif x.is_a?(Numeric) || !(x.to_s =~ NUMERIC_REGEX).nil?
return !x.to_f.zero?
elsif x.is_a?(String)
return x != "false" && x != "0" && x != ""
Expand All @@ -44,7 +44,7 @@ def boolean_convert(x)
def number_convert(x)
return if x.nil? || x.to_s.empty?

if x.is_a?(Numeric) || !(x =~ NUMERIC_REGEX).nil?
if x.is_a?(Numeric) || !(x.to_s =~ NUMERIC_REGEX).nil?
return x.to_f
elsif x.is_a?(TrueClass) || x.is_a?(FalseClass)
return x ? 1.0 : 0.0
Expand All @@ -57,7 +57,7 @@ def string_convert(x)
return x
elsif x.is_a?(TrueClass) || x.is_a?(FalseClass)
return x.to_s
elsif x.is_a?(Numeric) || !(x =~ NUMERIC_REGEX).nil?
elsif x.is_a?(Numeric) || !(x.to_s =~ NUMERIC_REGEX).nil?
return x == x.to_i ? x.to_i.to_s : x.to_s
end
nil
Expand Down
38 changes: 38 additions & 0 deletions spec/context_spec.rb
Expand Up @@ -698,6 +698,44 @@ def faraday_response(content)
expect(variable_experiments).to eq(context.variable_keys)
end

it "getCustomFieldKeys" do
context = create_context(data_future_ready)

expect(["country", "languages", "overrides"]).to eq(context.custom_field_keys)
end

it "getCustomFieldValues" do
context = create_context(data_future_ready)

expect(context.custom_field_value("not_found", "not_found")).to be_nil
expect(context.custom_field_value("exp_test_ab", key: "not_found")).to be_nil
expect(context.custom_field_value("exp_test_ab", "country")).to eq("US,PT,ES,DE,FR")
expect(context.custom_field_type("exp_test_ab", "country")).to eq("string")

data = {"123": 1, "456": 0}
expect(context.custom_field_value("exp_test_ab", "overrides")).to eq(data)
expect(context.custom_field_type("exp_test_ab", "overrides")).to eq("json")

expect(context.custom_field_value("exp_test_ab", "languages")).to be_nil
expect(context.custom_field_type("exp_test_ab", "languages")).to be_nil

expect(context.custom_field_value("exp_test_abc", "overrides")).to be_nil
expect(context.custom_field_type("exp_test_abc", "overrides")).to be_nil

expect(context.custom_field_value("exp_test_abc", "languages")).to eq("en-US,en-GB,pt-PT,pt-BR,es-ES,es-MX")
expect(context.custom_field_type("exp_test_abc", "languages")).to eq("string")

expect(context.custom_field_value("exp_test_no_custom_fields", "country")).to be_nil
expect(context.custom_field_type("exp_test_no_custom_fields", "country")).to be_nil

expect(context.custom_field_type("exp_test_no_custom_fields", "overrides")).to be_nil
expect(context.custom_field_value("exp_test_no_custom_fields", "overrides")).to be_nil

expect(context.custom_field_type("exp_test_no_custom_fields", "languages")).to be_nil
expect(context.custom_field_value("exp_test_no_custom_fields", "languages")).to be_nil

end

it "peek_treatmentReturnsOverrideVariant" do
context = create_ready_context

Expand Down
8 changes: 8 additions & 0 deletions spec/default_context_data_deserializer_spec.rb
Expand Up @@ -32,6 +32,10 @@
ExperimentVariant.new("A", nil),
ExperimentVariant.new("B", "{\"banner.border\":1,\"banner.size\":\"large\"}")
]
experiment0.custom_field_values = [
CustomFieldValue.new("country", "US,PT,ES,DE,FR", "string"),
CustomFieldValue.new("overrides", "{\"123\":1,\"456\":0}", "json"),
]
experiment0.audience_strict = false
experiment0.audience = nil

Expand All @@ -53,6 +57,10 @@
ExperimentVariant.new("B", "{\"button.color\":\"blue\"}"),
ExperimentVariant.new("C", "{\"button.color\":\"red\"}")
]
experiment1.custom_field_values = [
CustomFieldValue.new("country", "US,PT,ES,DE,FR", "string"),
CustomFieldValue.new("languages", "en-US,en-GB,pt-PT,pt-BR,es-ES,es-MX", "string"),
]
experiment1.audience_strict = false
experiment1.audience = ""

Expand Down
31 changes: 28 additions & 3 deletions spec/fixtures/resources/context.json
Expand Up @@ -33,7 +33,19 @@
"config":"{\"banner.border\":1,\"banner.size\":\"large\"}"
}
],
"audience": null
"audience": null,
"customFieldValues": [
{
"name": "country",
"value": "US,PT,ES,DE,FR",
"type": "string"
},
{
"name": "overrides",
"value": "{\"123\":1,\"456\":0}",
"type": "json"
}
]
},
{
"id":2,
Expand Down Expand Up @@ -73,7 +85,19 @@
"config":"{\"button.color\":\"red\"}"
}
],
"audience": ""
"audience": "",
"customFieldValues": [
{
"name": "country",
"value": "US,PT,ES,DE,FR",
"type": "string"
},
{
"name": "languages",
"value": "en-US,en-GB,pt-PT,pt-BR,es-ES,es-MX",
"type": "string"
}
]
},
{
"id":3,
Expand Down Expand Up @@ -113,7 +137,8 @@
"config":"{\"card.width\":\"75%\"}"
}
],
"audience": "{}"
"audience": "{}",
"customFieldValues": null
},
{
"id":4,
Expand Down

0 comments on commit 876489c

Please sign in to comment.