Ecto.ParameterizedType поведение
Исходный кодПараметризованные типы — это типы Ecto, которые можно настраивать отдельно для каждого поля.
Параметризованные типы позволяют указать в схеме набор параметров, которые инициализируются при компиляции и передаются функциям обратного вызова в качестве последнего аргумента.
Например, field :foo, :string ведет себя одинаково для всех полей. С другой стороны, field :foo, Ecto.Enum, values: [:foo, :bar, :baz], скорее всего, будет иметь разные наборы значений для разных полей.
Обратите внимание, что параметры указываются в виде ключевого списка, однако идиоматично преобразовывать их в карты внутри init/1, чтобы упростить сопоставление с образцом в других функциях обратного вызова.
Параметризованные типы являются надмножеством обычных типов. Иными словами, с помощью параметризованных типов можно делать все то же, что и с обычными, и даже больше. Например, параметризованные типы могут обрабатывать значения nil в функциях обратного вызова load и dump, настраивать поведение cast для каждого запроса и набора изменений, а также управлять встраиванием значений.
Однако параметризованные типы также сложнее. Поэтому, если все необходимое можно реализовать с помощью базовых типов, предпочтительнее использовать именно их.
Примеры
Чтобы создать параметризованный тип, создайте модуль, как показано ниже:
defmodule MyApp.MyType do
use Ecto.ParameterizedType
def type(_params), do: :string
def init(opts) do
validate_opts(opts)
Enum.into(opts, %{})
end
def cast(data, params) do
...
{:ok, cast_data}
end
def load(data, _loader, params) do
...
{:ok, loaded_data}
end
def dump(data, dumper, params) do
...
{:ok, dumped_data}
end
def equal?(a, b, _params) do
a == b
end
end
Чтобы использовать этот тип в поле схемы, укажите тип и параметры следующим образом:
schema "foo" do field :bar, MyApp.MyType, opt1: :baz, opt2: :boo end
Чтобы использовать этот тип в поле схемы с составным типом, укажите тип в кортеже, а затем параметры opts.
schema "foo" do
field :bars, {:array, MyApp.MyType}, opt1: :baz, opt2: :boo
end
Чтобы использовать этот тип в местах, где его необходимо инициализировать (например, в наборах изменений без схемы), можно воспользоваться функцией init/2.
use Ecto.ParameterizedType
При вызове use Ecto.ParameterizedType будет установлено @behaviour Ecto.ParameterizedType, а также определены реализации по умолчанию с возможностью переопределения для embed_as/2 и equal?/3.
Краткое описание
- params()
Параметры для ParameterizedType
Типы
- autogenerate(params)
Создает загруженную версию данных.
- cast(data, params)
Приводит заданные входные данные к ParameterizedType с указанными параметрами.
- dump(value, dumper, params)
Сохраняет заданный терм в собственном типе Ecto.
- embed_as(format, params)
Определяет, как следует обрабатывать тип внутри встраиваемых структур.
- equal?(value1, value2, params)
Проверяет, равны ли два терма семантически.
- format(params)
Форматирует вывод, когда ParameterizedType отображается в исключениях и других журналах.
- init(opts)
Функция обратного вызова, преобразующая параметры, указанные в макросе поля, в параметры для других функций обратного вызова.
- load(value, loader, params)
Загружает заданный терм в ParameterizedType.
- type(params)
Возвращает базовый тип схемы для ParameterizedType.
Функции обратного вызова
- init(type, opts)
Инициализирует параметризованный тип, заданный
type, с помощьюopts.
Функции
Типы
opts()Исходный код
@type opts() :: keyword()
Параметры в виде ключевого списка, передаваемые из макроса поля схемы в init/1
params()Исходный код
@type params() :: term()
Параметры для ParameterizedType
Это значение возвращается из init/1, а затем передается в качестве последнего аргумента всем функциям обратного вызова. Идиоматично использовать для этого карту.
Функции обратного вызова
autogenerate(params)Исходный код
@callback autogenerate(params()) :: term()
Создает загруженную версию данных.
Эта функция обратного вызова вызывается, когда параметризованный тип передается в field с флагом :autogenerate.
cast(data, params)Исходный код
@callback cast(data :: term(), params()) :: {:ok, term()} | :error | {:error, keyword()} Приводит заданные входные данные к ParameterizedType с указанными параметрами.
Если параметризованный тип также является составным типом, внутренний тип можно привести, напрямую вызвав Ecto.Type.cast/2.
Дополнительные сведения о приведении типов см. в разделе Ecto.Type.cast/1.
dump(value, dumper, params)Исходный код
@callback dump(value :: any(), dumper :: function(), params()) ::
{:ok, value :: any()} | :error Сохраняет заданный терм в собственном типе Ecto.
Если параметризованный тип также является составным типом, функция получает функцию dumper. Чтобы сохранить внутренний тип, необходимо вызвать dumper, передав ей внутренний тип и внутреннее значение в качестве аргументов.
Дополнительные сведения о сохранении см. в разделе Ecto.Type.dump/1. Обратите внимание, что эта функция обратного вызова будет вызвана при сохранении значения nil, в отличие от Ecto.Type.dump/1.
embed_as(format, params)Исходный код
@callback embed_as(format :: atom(), params()) :: :self | :dump
Определяет, как следует обрабатывать тип внутри встраиваемых структур.
Дополнительные сведения о встраивании см. в разделе Ecto.Type.embed_as/1
equal?(value1, value2, params)Исходный код
@callback equal?(value1 :: any(), value2 :: any(), params()) :: boolean()
Проверяет, равны ли два терма семантически.
format(params)Исходный код
@callback format(params()) :: String.t()
Форматирует вывод, когда ParameterizedType отображается в исключениях и других журналах.
Обратите внимание, что эта функция обратного вызова не используется при создании ошибок проверки Ecto.Changeset. Сведения о настройке сообщений об ошибках для каждого Ecto.Changeset см. в описании параметра :message большинства функций проверки Ecto.Changeset.
init(opts)Исходный код
@callback init(opts :: opts()) :: params()
Функция обратного вызова, преобразующая параметры, указанные в макросе поля, в параметры для других функций обратного вызова.
Эта функция вызывается во время компиляции и должна вызывать исключение, если указаны недопустимые значения. Идиоматично, чтобы возвращаемые ею параметры представляли собой карту. Параметры field и schema автоматически добавляются в список параметров.
Например, эта спецификация схемы
schema "my_table" do field :my_field, MyParameterizedType, opt1: :foo, opt2: nil end
приведет к вызову:
MyParameterizedType.init([schema: "my_table", field: :my_field, opt1: :foo, opt2: nil])
load(value, loader, params)Исходный код
@callback load(value :: any(), loader :: function(), params()) ::
{:ok, value :: any()} | :error Загружает заданный терм в ParameterizedType.
Если параметризованный тип также является составным типом, функция получает функцию loader. Чтобы загрузить внутренний тип, необходимо вызвать loader, передав ей внутренний тип и внутреннее значение в качестве аргументов.
Дополнительные сведения о загрузке см. в разделе Ecto.Type.load/1. Обратите внимание, что эта функция обратного вызова будет вызвана при загрузке значения nil, в отличие от Ecto.Type.load/1.
type(params)Исходный код
@callback type(params()) :: Ecto.Type.t()
Возвращает базовый тип схемы для ParameterizedType.
Дополнительные сведения о типах схем см. в разделе Ecto.Type.type/0
Функции
init(type, opts)Исходный код
Инициализирует параметризованный тип, заданный type, с помощью opts.
Полезно при ручной инициализации типа для наборов изменений без схемы.
© 2014 Chris McCord
Licensed under the MIT License.
https://ecto.hexdocs.pm/Ecto.ParameterizedType.html