Ecto Changeset添加警告功能

Ada*_*uda 6 functional-programming elixir extending ecto phoenix-framework

我创建了一个ecto存储库分支来扩展Ecto.Changeset模块,并能够向变更集添加警告.我希望有一个 add_warnings/4函数可以将变更集添加警告,作为具有此结构的警告的简单列表warnings: [{atom, {String.t, Keyword.t}}],类似于errors.warnings和的行为之间的区别在于errors,当发生错误时,数据不会被持久化,但是当发生警告时,数据会被持久化.

Ecto.Changeset结构扩展了键warningswarningless?:

defstruct valid?: false, warningless?: false, data: nil, params: nil, changes: %{}, repo: nil,
        errors: [], warnings: [], validations: [], required: [], prepare: [],
        constraints: [], filters: %{}, action: nil, types: nil,
        empty_values: @empty_values
Run Code Online (Sandbox Code Playgroud)

Ecto用于调整铸造,更改,处理参数等功能.功能add_warnings/4添加:

@spec add_warning(t, atom, String.t, Keyword.t) :: t
def add_warning(%{warnings: warnings} = changeset, key, message, keys \\ []) when is_binary(message) do
  %{changeset | warnings: [{key, {message, keys}}|warnings], warningless?: false}
end 
Run Code Online (Sandbox Code Playgroud)

结果是我收到changeset了预期的密钥:

#Ecto.Changeset<action: nil, changes: %{}, data: #Company.Booking<>, errors: [],
valid?: true, warnings: [], warningless?: true>
Run Code Online (Sandbox Code Playgroud)

当我做出更改时出现错误并收到警告:

#Ecto.Changeset<action: nil,
changes: %{pickup_address: #Ecto.Changeset<action: :update,
changes: %{street_name: nil}, data: #Company.Address<>,
errors: [street_name: {"can't be blank", [validation: :required]}],
valid?: false,
warnings: [phone_number: {"This phone number is not common in Netherlands",
  []}], warningless?: false>}, data: #Company.Booking<>, errors: [],
valid?: false, warnings: [], warningless?: true>
Run Code Online (Sandbox Code Playgroud)

因此,就警告而言,一切都如预期的那样.然后,当我通过警告进行更改但没有错误时,我收到:

#Ecto.Changeset<action: nil,
changes: %{pickup_address: #Ecto.Changeset<action: :update,
changes: %{street_name: "sss"}, data: #Company.Address<>, errors: [],
valid?: true,
warnings: [phone_number: {"This phone number is not common in Netherlands",
  []}], warningless?: false>}, data: #Company.Booking<>, errors: [],
valid?: true, warnings: [], warningless?: true>
Run Code Online (Sandbox Code Playgroud)

一切都如预期.当我不对表格进行任何更改时,我仍然会收到电话号码的警告,但我收到:

#Ecto.Changeset<action: nil, changes: %{}, data: #Company.Booking<>,    errors: [],
valid?: true, warnings: [], warningless?: true>
Run Code Online (Sandbox Code Playgroud)

changes由于数据没有改变,因为变更集中没有密钥,因此我没有任何警告就收到了变更集.

问题如下,即使没有进行任何更改,如何实现警告功能以始终在变更集中有警告?

Pat*_*wak 1

您应该考虑在您要创建的每个函数的开头预先填充警告changeset- 因为您不能使用plug在那里使用,所以您可以编写一个宏来为您处理这个逻辑,__using__建议,所以这将是相当好的轻松区分您的逻辑和 Ecto 的默认逻辑。

您的验证不应将警告添加到警告列表中,但您必须以另一种方式实现它 - 如果该字段正常,您将从该列表中删除已经存在的警告。这样,您就可以确保您的变更集在 时没有问题warningless,因为它从此列表中删除了所有警告,并且它可以完美地处理变更集中的空变更。