Skip to content

Commit

Permalink
feat: support IN operator for local evaluation (#33)
Browse files Browse the repository at this point in the history
feat: support `IN` operator for local evaluation
  • Loading branch information
khvn26 authored Jul 19, 2023
2 parents ef3651d + 7ae0ef6 commit 83abd38
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 17 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,7 @@ flagsmith_engine-*.tar
# Ignore the dialyzer PLTS
/priv/plts

# ElixirLS
.elixir_ls

.vscode/
32 changes: 17 additions & 15 deletions lib/flagsmith_engine.ex
Original file line number Diff line number Diff line change
Expand Up @@ -442,17 +442,8 @@ defmodule Flagsmith.Engine do
trait_value: t_value
} ->
case prop == t_key do
true ->
case cast_value(t_value, value) do
{:ok, casted} ->
trait_match(operator, casted, t_value)

_ ->
false
end

_ ->
false
true -> trait_match(operator, value, t_value)
_ -> false
end
end)
end
Expand Down Expand Up @@ -580,10 +571,21 @@ defmodule Flagsmith.Engine do
end
end

def trait_match(:MODULO, trait, %Trait.Value{value: value}) do
with true <- is_binary(trait),
def trait_match(:IN, condition_value, %Trait.Value{type: :string, value: t_value}) do
Enum.member?(String.split(condition_value, ","), t_value)
end

def trait_match(:IN, condition_value, %Trait.Value{
type: :decimal,
value: %Decimal{exp: 0} = t_value
}) do
Enum.member?(String.split(condition_value, ","), t_value |> Decimal.to_string())
end

def trait_match(:MODULO, condition_value, %Trait.Value{value: value}) do
with true <- is_binary(condition_value),
%Decimal{} <- value,
[mod, result] <- String.split(trait, "|"),
[mod, result] <- String.split(condition_value, "|"),
%Decimal{} = mod_val <- Decimal.new(mod),
%Decimal{} = result_val <- Decimal.new(result),
%Decimal{} = remainder <- Decimal.rem(value, mod_val) do
Expand All @@ -595,7 +597,7 @@ defmodule Flagsmith.Engine do
rescue
Decimal.Error ->
Logger.warn(
"invalid MODULO segment rule or trait value :: rule: #{inspect(trait)} :: value: #{inspect(value)}"
"invalid MODULO segment rule or trait value :: rule: #{inspect(condition_value)} :: value: #{inspect(value)}"
)

false
Expand Down
3 changes: 2 additions & 1 deletion lib/schemas/types/operator.ex
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ defmodule Flagsmith.Schemas.Types.Operator do
:IS_SET,
:IS_NOT_SET,
:MODULO,
:PERCENTAGE_SPLIT
:PERCENTAGE_SPLIT,
:IN
]
end
13 changes: 12 additions & 1 deletion test/unit/segment_conditions_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,18 @@ defmodule Flagsmith.Engine.SegmentConditionsTest do
{:MODULO, "1.0.0", "3|0", false},
{:MODULO, false, "1|3", false},
{:MODULO, 3.5, "1.5|0.5", true},
{:MODULO, 4, "1.5|0.5", false}
{:MODULO, 4, "1.5|0.5", false},
{:IN, "foo", "", false},
{:IN, "foo", "foo,bar", true},
{:IN, "bar", "foo,bar", true},
{:IN, "ba", "foo,bar", false},
{:IN, 1, "1,2,3,4", true},
{:IN, 1, "", false},
{:IN, 1, "1", true},
# Flagsmith's engine does not evaluate `IN` condition for floats/doubles and booleans
# due to ambiguous serialization across supported platforms.
{:IN, 1.5, "1.5", false},
{:IN, false, "false", false}
]

test "all conditions" do
Expand Down

0 comments on commit 83abd38

Please sign in to comment.