【发布时间】:2018-05-06 18:25:30
【问题描述】:
我有一个用户架构
schema "users" do
field :name, :string
field :username, :string
has_one :user_role, UserRole
end
def changeset(%User{} = user, attrs) do
user
|> cast(attrs, [:name, :username])
|> validate_required([:name, :username])
|> unique_constraint(:username)
end
和 UserRole 架构
schema "userroles" do
field :is_admin, :boolean, default: false
belongs_to :user, User
end
def changeset(%UserRole{} = user_role, attrs) do
user_role
|> cast(attrs, [:is_admin, :user_id])
|> validate_required([:is_admin])
end
它们都在同一个上下文“帐户”中,我在其中进行关联。
#accounts.ex
def create_user(attrs \\ %{}) do
%User{}
|> User.changeset(attrs)
|> Ecto.Changeset.cast_assoc(:user_role, required: true)
|> Repo.insert()
end
这是 UserController 的新建和创建:
def new(conn, _params) do
changeset = Accounts.change_user(%User{})
render(conn, "new.html", changeset: changeset)
end
def create(conn, %{"user" => user_params}) do
case Accounts.create_user(user_params) do
{:ok, user} ->
conn
|> put_flash(:info, "User created successfully.")
|> redirect(to: user_path(conn, :show, user))
{:error, %Ecto.Changeset{} = changeset} ->
render(conn, "new.html", changeset: changeset)
end
end
我有一个 User 和 UserRole 的嵌套表单。如果我输入所有数据,一切都会按预期进行。现在,我想隐藏 UserRole 的输入,因为我不希望用户将自己设置为“is_admin”(但如果您是管理员,您应该能够创建其他管理员帐户)。因此,如果您是非管理员用户,则不再需要输入 UserRole。我的期望是
- 如果没有输入,则将插入来自 UserRole 架构的默认值或
- UserRole 变更集中的验证表明没有输入,但它是必需的。
发生的情况是:用户已创建,但关联的 user_role 为“nil”。我不明白为什么会这样。谁能给我解释一下?
我的解决方案是:我没有给用户一个布尔值 :is_admin 的复选框,而是发送一个隐藏输入,将其设置为 false,但这似乎不是好方法。
【问题讨论】:
-
补充:在 UserController 的 create 动作中,甚至没有在 user_params 中插入 :user_role 键。我删除了表单中的隐藏输入,现在我正在检查 user_params 中的 :user_role 键。如果没有,我创建一个新的 %UserRole{is_admin: false} 变更集并使用 put_assoc 插入它。这行得通,但我不明白为什么这是必要的,或者更确切地说,为什么没有使用默认值“false”插入 :user_role。