11

我想知道是否有一种方法可以使用ElixirPhoenix框架创建表单对象?我想实现类似于reformgem 所做的事情,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
4

1 回答 1

15

这可以在具有虚拟属性的模式上工作:

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
于 2015-08-13T12:30:46.220 回答