如何使用一个字段的转换值作为 Ecto 中另一个字段的默认值
How to use a cast value of one field as a default for another field in Ecto
编辑:我想我想问的是如何做:
board.members[1].username = owner
我正在尝试使对象(用户输入)的 owner
成为其 members
中的一个,这是一个将成员名称与其角色相关联的映射,两者都是字符串。这应该在创建新对象时发生。
编辑:我很抱歉试图让它变得简单
defmodule Vision.Boards.Board do
use Ecto.Schema
import Ecto.Changeset
schema "boards" do
field :members, :map
field :owner, :string
field :team_name, :string
field :title, :string
timestamps()
end
@doc false
def changeset(board, attrs) do
board
|> cast(attrs, [:title, :owner, :team_name])
|> validate_required([:title, :owner, :team_name])
board =
Repo.insert! %Board{members: %{:owner => "Manage"}}
end
end
另外,这个field :members, :map, default: %{:owner => "Manage"}
使用 Repo.insert 你会立即跳转到数据库......为什么不像
board
|> cast(attrs, [:title, :owner, :team_name])
|> validate_required([:title, :owner, :team_name])
|> put_change(:members, %{:owner => "Manage"})
当然是为了处理不同的行为,could/should 被提取到函数中并以相同的方式调用...但是为了简单的创建,应该这样做。
不幸的是,Ecto
不支持允许您执行此操作的内置功能。您可以通过以下方式实现它:
defmodule Vision.Boards.Board do
use Ecto.Schema
import Ecto.Changeset
# ..
@doc false
def changeset(board, attrs) do
board
|> cast(attrs, [:members, :title, :owner, :team_name])
|> cast_default_members_from_owner()
|> validate_required([:members, :title, :owner, :team_name])
end
defp cast_default_members_from_owner(changeset) do
struct = apply_changes(changeset)
if is_nil(struct.members) and not is_nil(struct.owner) do
put_change(changeset, :members, %{struct.owner => "Manage"})
else
changeset
end
end
end
快速提示:
在 cast
之后用 :members
调用 cast_default_members_from_owner
允许您使用 %{struct.owner => "Manage"}
作为默认值,它可以在 attrs
中被覆盖,并在之前调用它validate_required
允许您确保始终应用默认值。
编辑:我想我想问的是如何做:
board.members[1].username = owner
我正在尝试使对象(用户输入)的 owner
成为其 members
中的一个,这是一个将成员名称与其角色相关联的映射,两者都是字符串。这应该在创建新对象时发生。
编辑:我很抱歉试图让它变得简单
defmodule Vision.Boards.Board do
use Ecto.Schema
import Ecto.Changeset
schema "boards" do
field :members, :map
field :owner, :string
field :team_name, :string
field :title, :string
timestamps()
end
@doc false
def changeset(board, attrs) do
board
|> cast(attrs, [:title, :owner, :team_name])
|> validate_required([:title, :owner, :team_name])
board =
Repo.insert! %Board{members: %{:owner => "Manage"}}
end
end
另外,这个field :members, :map, default: %{:owner => "Manage"}
使用 Repo.insert 你会立即跳转到数据库......为什么不像
board
|> cast(attrs, [:title, :owner, :team_name])
|> validate_required([:title, :owner, :team_name])
|> put_change(:members, %{:owner => "Manage"})
当然是为了处理不同的行为,could/should 被提取到函数中并以相同的方式调用...但是为了简单的创建,应该这样做。
不幸的是,Ecto
不支持允许您执行此操作的内置功能。您可以通过以下方式实现它:
defmodule Vision.Boards.Board do
use Ecto.Schema
import Ecto.Changeset
# ..
@doc false
def changeset(board, attrs) do
board
|> cast(attrs, [:members, :title, :owner, :team_name])
|> cast_default_members_from_owner()
|> validate_required([:members, :title, :owner, :team_name])
end
defp cast_default_members_from_owner(changeset) do
struct = apply_changes(changeset)
if is_nil(struct.members) and not is_nil(struct.owner) do
put_change(changeset, :members, %{struct.owner => "Manage"})
else
changeset
end
end
end
快速提示:
在 cast
之后用 :members
调用 cast_default_members_from_owner
允许您使用 %{struct.owner => "Manage"}
作为默认值,它可以在 attrs
中被覆盖,并在之前调用它validate_required
允许您确保始终应用默认值。