Объекты формы с каркасом Elixir и Phoenix
Интересно, есть ли способ создания объектов формы с Elixir
а также Phoenix
фреймворк? Я хочу реализовать что-то похожее на то, что reform
драгоценный камень делает в Rails
потому что мне не нравится, когда в каждом случае выполняются одинаковые проверки, это приводит к сложному коду в моем опыте. Так можно ли создать что-то вроде следующего и заставить его работать как-то?
defmodule RegistrationForm do
defstruct email: nil, password: nil, age: nil
import Ecto.Changeset
def changeset(model, params \\ :empty) do
model
|> cast(params, ["email", "password", "age"], ~w())
|> validate_length(:email, min: 5, max: 240)
|> validate_length(:password, min: 8, max: 240)
|> validate_inclusion(:age, 0..130)
end
end
1 ответ
Решение
Это может работать в схеме с виртуальными атрибутами:
defmodule RegistrationForm do
use Ecto.Schema
import Ecto.Changeset
schema "" do
field :email, :string, virtual: true
field :password, :string, virtual: true
field :age, :integer, virtual: true
end
def changeset(model, params \\ :empty) do
model
|> cast(params, ["email", "password", "age"], ~w())
|> validate_length(:email, min: 5, max: 240)
|> validate_length(:password, min: 8, max: 240)
|> validate_inclusion(:age, 0..130)
end
end
Это также может работать, если вы укажете __changeset__
функция или значение в вашей структуре (это автоматически генерируется schema
макрос.) - однако кажется, что это может быть не намеренным способом сделать это.
defmodule RegistrationForm do
defstruct email: nil, password: nil, age: nil
import Ecto.Changeset
def changeset(model, params \\ :empty) do
model
|> cast(params, ["email", "password", "age"], ~w())
|> validate_length(:email, min: 5, max: 240)
|> validate_length(:password, min: 8, max: 240)
|> validate_inclusion(:age, 0..130)
end
def __changeset__ do
%{email: :string, password: :string, age: :integer}
end
end
Оба дают следующие результаты:
iex(6)> RegistrationForm.changeset(%RegistrationForm{}, %{email: "user@example.com", password: "foobarbaz", age: 12}).valid?
true
iex(7)> RegistrationForm.changeset(%RegistrationForm{}, %{email: "user@example.com", password: "foobarbaz", age: 140}).valid?
false