Объекты формы с каркасом 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
Другие вопросы по тегам