Получить значение карты из строки Code.eval в Elixir - PullRequest
1 голос
/ 16 апреля 2020

Я пытаюсь получить значение карты, запустив Code.eval_string / 1, и он завершается ошибкой:

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

Код:

  @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

, затем я запускаю:

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

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


RulesEngine.evaluate_object_by_condition(obj, rules_or)

Итак, я пытаюсь получить значение data.tiene_beca и получить имя переменной из строки, что будет правильным способом сделать это в эликсире?

1 Ответ

2 голосов
/ 16 апреля 2020

Прежде всего, подумайте, нужна ли вам вся эта гибкость. Code.eval_string запускает код без каких-либо проверок или ограничений, так что это потенциально открывает дыру в безопасности кода. Вместо этого я бы сделал что-то вроде этого:

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

Тем не менее, ваш код не работает, потому что Code.eval_string не имеет доступа к локальным переменным в вызывающей функции, поэтому вам нужно явно передать переменную как привязку:

    eval_data = Code.eval_string(attr, [data: data])
...