我有一个用户架构
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
我有一个用户和UserRole的嵌套表单。如果我输入所有数据,一切都按预期工作。现在,我想隐藏UserRole的输入,因为我不希望用户将自己设置为“is_admin”(但如果您是管理员,则应该能够创建其他管理员帐户)。因此,如果您是非管理员用户,则不再有UserRole的输入。我的期望是这样的
发生的事情是:用户已创建,但关联的user_role为“nil”。我不明白为什么会这样。任何人都可以向我解释一下吗?
我的解决方案是:不是给用户一个布尔值的复选框:is_admin,我发送一个隐藏的输入,将其设置为false,但它似乎不是好方法。
你可以随时使用
在这种情况下Map.put_new(map, key, value)
之前
case Accounts.create_user(user_params) do
使用params = Map.put_new(user_params, :user_role, "anything")
这将做的是,如果它在地图中找到:user_role
,它将使用相同的,如果它没有找到任何东西,它将使用你指定的值。
它需要user_role
的值,因为有一个与之相关的关联。虽然我觉得它应该是has_many
协会,但你的代码显示其has_one
,所以对于每个user
条目应该有user_role
相关联。
如果要使用has_many
,belongs_to
应该在user
模式中,而has_many
在user_role
模式中