仅针对插入操作自定义变更集验证

时间:2016-02-17 16:19:58

标签: model crud elixir phoenix-framework

我正在开展凤凰项目。我有以下型号:

defmodule MyApp.Exam do
  use MyApp.Web, :model

  alias Ecto.Changeset
  alias MyApp.Repo
  alias MyApp.TimexHelper
  alias Timex.Date

  import Ecto.Query

  schema "exams" do
      field :start_time, Timex.Ecto.DateTime
      belongs_to :student, Student

      timestamps
  end

  @required_fields ~w(student_id start_time)

  def changeset(model, params \\ :empty) do
      model
      |> cast(params, @required_fields, @optional_fields)
      |> assoc_constraint(:student)
      |> is_in_future(:start_time)
  end

  def is_in_future(changes, field) do
      new_time = Changeset.get_field(changes, field)
      valid = TimexHelper.compare(new_time, Date.now)
      if !valid, do: changes = Changeset.add_error(changes, field, "should be in the future")
      changes
  end
end

如何仅在is_in_future操作期间对字段start_time进行自定义验证insert

我尝试在if中添加is_in_future条件,以检查start_time是否可用。但我认为这不是一个更好的解决方案。

我正在寻找类似的东西:

# Rails model field validation
validates_presence_of :start_time, :on => :create

1 个答案:

答案 0 :(得分:1)

我不确定,但我认为没有类似rails的解决方案。您将在数据库调用之前创建变更集和验证。之后,您自己插入/更新模型。验证后,强制转换方法没有关于数据库调用的信息。

我的想法是在变更集函数中添加类似布尔值或原子的参数来定义验证类型。

func changeset(model, params \\ :empty, type \\ :insert) do
  changeset = model
    |> cast(params, @required_fields, @optional_fields)
    |> assoc_constraint(:student)

  case type do
    :insert ->
      is_in_future(changeset, :start_time)
    :update ->
      changeset
  end
end

然后你应该致电changeset(model, params, :insert)changeset(model, params, :update)

希望它有所帮助。

编辑: 另一个想法是检查模型的id是否设置为nil。这与现有start_time字段的想法相似。