I’ve written a few changeset functions, each for the corresponding field in the user schema. I’m now thinking about how to best tie them together for the registration_changeset
. I want to do that dynamically since I want to experiment with different ways a user can register, with or without email address, password, and/or phone number.
These are my current changeset functions for some of the fields in the schema:
def username_changeset(user, params \\ %{}) do
user
|> cast(params, [:username])
|> validate_required([:username])
|> validate_length(:username, min: 3, max: 20)
|> validate_format(:username, ~r/^[a-zA-Z0-9_]*$/)
|> update_change(:username, &String.downcase/1)
|> unique_constraint(:username)
end
def password_changeset(user, params \\ %{}) do
user
|> cast(params, [:password])
|> validate_required([:password])
|> validate_length(:password, min: 6, max: 100)
|> put_password_hash()
end
def email_address_changeset(user, params \\ %{}) do
user
|> cast(params, [:email_address])
|> validate_required([:email_address])
|> validate_format(:email_address, ~r/@/)
|> unique_constraint(:email_address)
end
def phone_number_changeset(user, params \\ %{}) do
user
|> cast(params, [:phone_number])
|> validate_required([:phone_number])
|> unique_constraint(:phone_number)
end
def avatar_changeset(user, params \\ %{}) do
cast_attachments(user, params, [:avatar])
end
def location_changeset(user, params \\ %{}) do
user
|> cast(params, [:location])
|> validate_required([:location])
|> put_district()
end
And I am considering writing something like this for the registration_changeset
:
def registration_changeset(user, params \\ %{}, fields) do
Enum.reduce(fields, %Ecto.Changeset{}, fn field, acc ->
merge(acc, apply(__MODULE__, :"#{field}_changeset", [user, params]))
end)
end
where merge/2
is imported from Ecto.Changeset
.
Is this overly complicated? Thanks