Ecto Changeset - 如果没有给出输入,则不进行关联

时间:2018-05-05 22:14:14

标签: elixir phoenix-framework

我有一个用户架构

  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的new和create:

  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的输入。我的期望是那个

  1. 如果没有输入或
  2. ,将插入UserRole架构的默认值
  3. UserRole的变更​​集中的验证会说没有输入,但它是必需的。
  4. 发生的事情是:用户已创建,但关联的user_role为“nil”。我不明白为什么会这样。任何人都可以向我解释一下吗?

    我的解决方案是:不是给用户一个布尔值:is_admin的复选框,而是发送一个隐藏的输入,将其设置为false,但这似乎不是好方法。

1 个答案:

答案 0 :(得分:1)

您可以随时使用

在这种情况下

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架构中