Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Form objects with Elixir and Phoenix framework

I wonder if there is a way to create form objects with Elixir and Phoenix framework? I want to implement something similar to what reform gem does in Rails because I don't like having same validations run in every case, it leads to a complicated code in my experience. So could I create something like the following and make it work somehow?

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
like image 822
NoDisplayName Avatar asked Aug 13 '15 12:08

NoDisplayName


1 Answers

This can work on a schema with virtual attributes:

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

This can also work if you specify an __changeset__ function or value in your struct (this is auto-generated by the schema macro.) - however it seems like this may not be an intentional way to do it.

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

Both give the following results:

iex(6)>  RegistrationForm.changeset(%RegistrationForm{}, %{email: "[email protected]", password: "foobarbaz", age: 12}).valid?
true
iex(7)>  RegistrationForm.changeset(%RegistrationForm{}, %{email: "[email protected]", password: "foobarbaz", age: 140}).valid?
false
like image 77
Gazler Avatar answered Oct 28 '22 06:10

Gazler