Elixir 如何在保存回调之前将EXTO变更集设计为true
我做了一个简单的前保存转换,并了解到phoenix使用EXTO changest执行此任务 我的Elixir 如何在保存回调之前将EXTO变更集设计为true,elixir,phoenix-framework,ecto,Elixir,Phoenix Framework,Ecto,我做了一个简单的前保存转换,并了解到phoenix使用EXTO changest执行此任务 我的阶段模型有一个位置属性,该属性默认为当前最大值+1,因此尝试如下实现: 舞台模型: def changeset(struct, params \\ %{}) do struct |> cast(params, @required_fields, @optional_fields) |> validate_required([:name]) |> s
阶段
模型有一个位置
属性,该属性默认为当前最大值+1
,因此尝试如下实现:
舞台模型:
def changeset(struct, params \\ %{}) do
struct
|> cast(params, @required_fields, @optional_fields)
|> validate_required([:name])
|> set_position
end
defp set_position(current_changeset) do
# get current max position from db
max_position = Repo.one(
from s in Stage,
select: fragment("COALESCE(MAX(?),0)", s.position)
)
case current_changeset do
%Ecto.Changeset{valid?: true} ->
put_change(current_changeset, :position, max_position+1)
_ ->
current_changeset
end
end
逐个插入记录时工作正常,但批量插入失败;例如,在下面的seed
文件中
种子
alias MyApp.{Repo, Post}
[
%{name: "Requirements"},
%{name: "Quotation"},
%{name: "Development"},
%{name: "Closing"}
]
|> Enum.map(&Post.changeset(%Post{}, &1))
|> Enum.each(&Repo.insert!(&1))
预期/当前行为:
def changeset(struct, params \\ %{}) do
struct
|> cast(params, @required_fields, @optional_fields)
|> validate_required([:name])
|> set_position
end
defp set_position(current_changeset) do
# get current max position from db
max_position = Repo.one(
from s in Stage,
select: fragment("COALESCE(MAX(?),0)", s.position)
)
case current_changeset do
%Ecto.Changeset{valid?: true} ->
put_change(current_changeset, :position, max_position+1)
_ ->
current_changeset
end
end
如果当前最大位置为7
,则对于上面插入的所有4条记录,位置将分别设置为8
,而不是8,9,10,11
!这是因为第一个管道将准备所有更改,然后插入它们
我播种的方式错了吗?还是变更集?我如何重新设计它,以便无论我如何进行插入,行为都是相同的?任何反馈,以改善我如何做它是感激的 您可以使用
exto.Changeset.prepare_changes/2
在该变更集的数据库事务中运行任意计算。您的set\u position/1
函数具有正确的参数/返回值(changeset->changeset),因此您只需更改:
|> set_position
到
和
set\u position
现在将在插入Post之前的同一事务中执行,而不是在创建变更集时执行。您可以使用exto.changeset.prepare\u changes/2
在该变更集的数据库事务中运行任意计算。您的set\u position/1
函数具有正确的参数/返回值(changeset->changeset),因此您只需更改:
|> set_position
到
而
set_position
现在将在插入帖子之前的同一事务中执行,而不是在创建变更集时执行。我没有尝试过这一点,但是将|>set_position
更改为|>准备变更(&set_position/1)
是否有效?插入记录时,应该在数据库事务中运行set_position
。使用一个枚举过程应该可以解决这个问题,我认为:[%{name:“Requirements”}、%{name:“quo引”}、%{name:“Development”}、%{name:“Closing”}>Enum.each(&Post.changeset(%Post{},&1)|>&Repo.insert!)
@Dogbert是的,这很好!谢谢新手问题/1是什么意思,是args的elxir数吗?那么,为什么它会导致没有它的异常呢?请发布一个接受的答案。@AbM你是对的,但我想让changest能够处理我插入的任何记录@Nimir是的,参数的数量。看见即使函数接受0个参数,该值也是必需的&foo
在Elixir中是无效的语法。我没有尝试过这一点,但是将|>设置_位置
更改为|>准备_更改(&set_位置/1)
有效吗?插入记录时,应该在数据库事务中运行set_position
。使用一个枚举过程应该可以解决这个问题,我认为:[%{name:“Requirements”}、%{name:“quo引”}、%{name:“Development”}、%{name:“Closing”}>Enum.each(&Post.changeset(%Post{},&1)|>&Repo.insert!)
@Dogbert是的,这很好!谢谢新手问题/1是什么意思,是args的elxir数吗?那么,为什么它会导致没有它的异常呢?请发布一个接受的答案。@AbM你是对的,但我想让changest能够处理我插入的任何记录@Nimir是的,参数的数量。看见即使函数接受0个参数,该值也是必需的<代码>&foo在Elixir中是无效语法。