Elixir: разрешить клиентам запускать некоторый предопределенный код, который оценивает - PullRequest
0 голосов
/ 25 сентября 2019

Я хочу, чтобы мои клиенты могли писать что-то вроде something <%= temp(@conn) %> something, где будет вызываться функция temp/1 из указанного модуля и выводиться всякий раз, когда я отображаю это.Набор функций будет очень ограничен и предопределен в этом случае, потому что я не хочу, чтобы они что-то убивали.

Как бы я поступил об этом?

Чтобы было понятно: у меня естьдатчики, которые имеют имена.Клиент может редактировать эти имена для отображения того, что они хотят, в формате, который они хотят, когда они идут на панель инструментов.

Ответы [ 2 ]

1 голос
/ 25 сентября 2019

Если замена строки не приведет вас туда, и вам нужен безопасный способ, позволяющий пользователям писать шаблоны, которые анализируются и обрабатываются на вашем сервере, тогда:

Это может бытьхорошо подходит для шаблонного движка типа жидкость (библиотека ruby).Существует реализация Elixir под названием liquid-elixir , я никогда с ней не работал, но у меня есть некоторый опыт работы с библиотекой Ruby.

Liquid предоставляет вам простой / ограниченный язык шаблонов, где вы можете добавлять теги, фильтры и предоставлять собственные локальные переменные.

Например, если вы назначите переменную с именем temp, которая будет содержать текущую температуру, пользователь может использовать ее в шаблоне:

The temperature is {{ temp | round: 2 }}.

{% if temp <= 0 %}
  It's freezing!
{% endif %}

Согласно readme liquid-elixir, для рендеринга этого на сервере (предположим, что выше указано в переменной user_template):

temperature = MyApp.Sensor.current_temperature()
template = Liquid.Template.parse(user_template)
{:ok, rendered, _} = Liquid.Template.render(template, %{"temp" => temperature})

А теперьу вас есть некоторый HTML-код в rendered, который вы можете использовать / display.

Опять же, у меня нет опыта работы с версией Elixir, я не знаю, полностью ли она работает или вообще работает.

0 голосов
/ 27 сентября 2019

Жидкий эликсир, предложенный Цвиппи, звучит как перебор (как он сказал).Поэтому я собираюсь опубликовать свое решение для тех, у кого может быть похожая проблема.Это намного меньше кода, чем я ожидал, и только немного менее гибким.

defmodule AppWeb.DSLHelper do
  @moduledoc false

  @pattern ~r/{{\s?([a-zA-Z_]*)\s?}}/

  def extract(name, message) do
    Regex.replace(@pattern, name, fn(_all, capture) -> replace(capture, message) end)
  end


  defp replace(what, message), do: "#{Map.get(message, what)}"
end

Люди теперь могут писать something {{temp}}°C и получать something 20.05°C

...