Hi, there
Goal:
can someone help me figure out why the field :gender can not save into database ?
- when I look into database, the :user_profile field it is still the default %{}. However, the user can be registered successfully and redirect to homepage.
Context:
the simple_form of user_registration_live.ex
file
<.simple_form
:let={f}
id="registration_form"
for={@changeset}
phx-submit="save"
phx-change="validate"
phx-trigger-action={@trigger_submit}
action={~p"/users/log_in?_action=registered"}
method="post"
as={:user}
>
<.error :if={@changeset.action == :insert}>
Oops, something went wrong! Please check the errors below.
</.error>
<.input field={{f, :email}} type="email" label="Email" required />
<.input field={{f, :password}} type="password" label="Password" required />
<.input field={{f, :username}} type="text" label="Username" required />
<.input
field={{f, :user_profile}}
name="user_profile[gender]"
type="select"
label="Gender"
options={["Female", "Male"]}
required
/>
<:actions>
<.button phx-disable-with="Creating account..." class="w-full">Create an account</.button>
</:actions>
</.simple_form>
users module
schema "users" do
field :email, :string
field :password, :string, virtual: true, redact: true
field :hashed_password, :string, redact: true
field :confirmed_at, :naive_datetime
field :username, :string
embeds_one :user_profile, UserProfile
timestamps()
end
def registration_changeset(user, attrs, opts \\ []) do
user
|> cast(attrs, [:email, :password, :username])
|> cast_embed(:user_profile)
|> validate_email(opts)
|> validate_username(opts)
|> validate_password(opts)
end
defp validate_username(changeset, opts) do
changeset
|> validate_required([:username])
|> validate_length(:username, min: 5, max: 30)
|> validate_format(:username, ~r/^[a-zA-Z0-9_.-]*$/,
message: "Please use letters and numbers without space(only characters allowed _ . -)"
)
|> maybe_validate_unique_username(opts)
end
user_profile
defmodule Cgc.Users.UserProfile do
@moduledoc """
The User profile schema.
Add arbitary user attributes here.
"""
use Cgc.Schema
import Ecto.Changeset
@primary_key false
embedded_schema do
field :gender, :string
field :avatar_url, :string, default: "/images/default-avatar.png"
field :dark_mode, :boolean, default: false
field :visibility, Ecto.Enum, values: [:public, :private, :friends_only], default: :private
end
# set @required_fields and @optional_fields
@required_fields ~w(gender)a
@optional_fields ~w(avatar_url dark_mode visibility)a
@doc false
def changeset(%__MODULE__{} = user_profile, attr \\ %{}) do
user_profile
|> cast(attr, @required_fields ++ @optional_fields)
|> validate_required(@required_fields)
|> validate_inclusion(:gender, ["Female", "Male"])
end
end
migration
defmodule Cgc.Repo.Migrations.CreateUsersAuthTables do
use Ecto.Migration
def change do
execute "CREATE EXTENSION IF NOT EXISTS citext", ""
create table(:users, primary_key: false) do
add :id, :binary_id, primary_key: true
add :email, :citext, null: false
add :hashed_password, :string, null: false
add :confirmed_at, :naive_datetime
add :username, :citext, null: false
add :user_profile, :map, default: %{}, null: false
timestamps()
end
create unique_index(:users, [:email])
create unique_index(:users, [:username])
create table(:users_tokens, primary_key: false) do
add :id, :binary_id, primary_key: true
add :user_id, references(:users, type: :binary_id, on_delete: :delete_all), null: false
add :token, :binary, null: false
add :context, :string, null: false
add :sent_to, :string
timestamps(updated_at: false)
end
create index(:users_tokens, [:user_id])
create unique_index(:users_tokens, [:context, :token])
end
end
Thanks!