1

Im trying to get the value of a map by running Code.eval_string/1 and it fails with error:

warning: variable "data" does not exist and is being expanded to "data()", please use parentheses to remove the ambiguity or change the variable name
  nofile:1

** (CompileError) nofile:1: undefined function data/0
    (elixir 1.10.2) lib/code.ex:332: Code.eval_string_with_error_handling/3
    main.exs:65: RulesEngine.evaluate_object_by_condition/2
    (elixir 1.10.2) lib/enum.ex:1396: Enum."-map/2-lists^map/1-0-"/2
    main.exs:17: RulesEngine.evaluate_object_by_condition/2

Code is:

  @doc "Evaluate condition"
  @default_op "="
  def evaluate_object_by_condition(data, condition) do
    IO.puts("Evaluando una regla en particular:")
    IO.inspect(condition)
    IO.inspect(data)
    attr = condition.attr
    value = condition.value
    IO.inspect(attr)
    eval_data = Code.eval_string(attr)
    op = Map.get(condition, "op", @default_op)
    IO.puts("DATA to EVAL")
    IO.inspect(eval_data)

    # value_type = Map.get(condition, "type")
    # Hacer type checking y agregar a value_type
    ## Falta obtener el valor del objeto
    # res = evaluate("=", value, obj.value)
    true
  end

then I run:

obj = %{
  value: 1,
  tiene_beca: 1,
  tiene_credito: 1
}

condition= %{
          attr: "data.tiene_beca",
          value: 1
        }   


RulesEngine.evaluate_object_by_condition(obj, rules_or)

So I'm trying to get the value of data.tiene_beca, and getting that variable name from a string, which would be the correct way of doing that in elixir?

1 Answer 1

2

First of all, consider whether you actually need all this flexibility. Code.eval_string runs the code without any checks or restrictions whatsoever, so this potentially opens a security hole in the code. I would do something like this instead:

["data", field_name] = String.split(attr, ".")
field_name = String.to_existing_atom(field_name)
eval_data = data[field_name]

That said, the reason your code isn't working is that Code.eval_string doesn't have access to local variables in the calling function, so you'd need to pass the variable as a binding explicitly:

    eval_data = Code.eval_string(attr, [data: data])
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks a lot for both the correct way of doing so in elixir and why it was failing!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.