使用现有条目在Ecto changeset函数中

huangapple go评论89阅读模式
英文:

Using existing entries in an Ecto changeset function

问题

我有一个business_hours表(使用MySQL),其中包含以下字段:

location_id(外键)
starting_time(浮点数 [例如,17 = 下午5点,17.5 = 下午5:30])
ending_time(浮点数)
day(整数 [0 = 星期一,6 = 星期日])

我的问题是,我应该如何创建一个Ecto changeset函数来验证新的business_hours条目是否与任何现有条目重叠?我知道一般情况下如何进行此检查(请参见下文),但我不确定如何将其集成到用于验证服务器端的changeset函数中。

(a.starting_time > b.ending_time or a.ending_time < b.starting_time) and a.day == b.day and a.location_id == b.location_id
英文:

I have a business_hours table (using MySQL) which contains the following fields:

location_id (foreign key)
starting_time (float [e.g. 17 = 5pm, 17.5 = 5:30pm])
ending_time (float)
day (integer [0 = monday, 6 = sunday])

My question is how would I go about creating an Ecto changeset function to validate that a new business_hours entry does not overlap any existing entry? I know how I would check for this in general (see below), but I am unsure on how to integrate this into a changeset function to validate this serverside.

(a.starting_time &gt; b.ending_time or a.ending_time &lt; b.starting_time) and a.day == b.day and a.location_id == b.location_id

答案1

得分: 1

请注意,changeset 是一个像任何其他结构体一样的结构,内置的验证函数接受 %Ecto.Changeset{} 结构体作为输入。您可以编写自己的函数,也接受此结构体作为输入,并可以通过手动修改 changeset 或使用提供的辅助函数(例如 Ecto.Changeset.add_error/2)来添加错误或值。

例如,在您的 Ecto 模式模块中,约定是在 changeset/2 函数内进行验证(但您也可以将此逻辑放在任何地方):

  def changeset(existing_data, attrs) do
    existing_data
    # 如果需要,可以使用 force_changes: true 选项,即使这些值与数据库中的值相同,也可以预设所有值以供评估
    |> cast(attrs, [:location_id, :starting_time, :ending_time, :day], force_changes: true)
    |> validate_required([:location_id, :starting_time, :ending_time, :day])
    |> foreign_key_constraint(:location_id)
    |> custom_business_logic()
  end

  # 这个函数可能需要 force_changes: true
  defp custom_business_logic(%Ecto.Changeset{changes: %{starting_time: starting_time, ending_time: ending_time, day: day}} = changeset) do
    case check_for_overlap(starting_time, ending_time, day) do
      :ok -> changeset
      _ -> add_error(changeset, :starting_time, "Uh oh... this time overlapped with some other location")
    end
  end

  defp check_for_overlap(starting_time, ending_time, day) do
    # 在这里执行自定义逻辑检查,例如查询数据库
    # 返回 :ok 或 {:error, "Something"}
  end

根据您的描述,您可能需要使您的自定义函数查询数据库,因此查询可以放在其中一个自定义验证函数中。

英文:

Remember that a changeset is a struct like any other, and the built-in validation functions accept an %Ecto.Changeset{} struct as input. You can write your own functions that also accept this as input and you can add errors or values by modifying the changeset manually or by using the provided helper functions (e.g. Ecto.Changeset.add_error/2).

For example, in your Ecto schema module, the convention is to do validation within a changeset/2 function (but you could put this logic anywhere):

  def changeset(existing_data, attrs) do
    existing_data
    # force_changes to true is a helpful option if you need to have all
    # values preset for evaluation even if they are unchanged from what&#39;s
    # already in the database
    |&gt; cast(attrs, [:location_id, :starting_time, :ending_time, :day], force_changes: true)
    |&gt; validate_required([:location_id, :starting_time, :ending_time, :day])
    |&gt; foreign_key_constraint(:location_id)
    |&gt; custom_business_logic()
  end

  # This function may require force_changes: true
  defp custom_business_logic(%Ecto.Changeset{changes: %{starting_time: starting_time, ending_time: ending_time, day: day}} = changeset) do
    case check_for_overlap(starting_time, ending_time, day) do
      :ok -&gt; changeset
      _ -&gt; add_error(changeset, :starting_time, &quot;Uh oh... this time overlapped with some other location&quot;)
    end
  end

  defp check_for_overlap(starting_time, ending_time, day) do
    # do custom logic check here, e.g. query database
    # return :ok or {:error, &quot;Something&quot;}
  end

From your description, you may need to have your custom function query the database, so that query could be housed in one of the custom validation functions.

huangapple
  • 本文由 发表于 2023年1月9日 19:25:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/75056587.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定