对PhoenixFramework变更集设置约束

时间:2016-10-11 04:38:16

标签: phoenix-framework

我在Phoenix Framework中有三个模型,UserPostVote用户只有在点数超过1分时才能对该帖子进行投票。用户点是通过他们的帖子从其他用户获得的票数来计算的。

这是我在Vote模型中定义的内容:

  schema "votes" do
    field :type, :integer # -1 0 1
    belongs_to :user, News.User
    belongs_to :post, News.Post

    timestamps()
  end

由于用户点未在Vote架构中定义,因此我无法直接在模型中使用validate_changeadd_error,除非我阅读其他模型'数据决定是否向变更集添加错误,显然它会在Vote模型中做太多事情。

我应该把约束放在哪里?控制器或型号?

也许我应该对数据库设置约束,确保用户点永远不会低于零?我找到了类似触发器的东西但PostgreSQL trigger将如何将结果返回到变更集?

更新(这个有效,但我不确定它是不是最好的方式)

我在我的控制器中试过了:

def create(conn, %{"vote" => vote_params}, user) do
    changeset = user
      |> build_assoc(:votes)
      |> Vote.changeset(vote_params)

    changeset = if user.point < 1 do
      Ecto.Changeset.add_error(changeset, :user_id, "You points is not enough.")
    end

    case Repo.insert(changeset) do
      {:ok, vote} ->
        conn
        |> put_status(:created)
        |> put_resp_header("location", vote_path(conn, :show, vote))
        |> render("show.json", vote: vote)
      {:error, changeset} ->
        conn
        |> put_status(:unprocessable_entity)
        |> render(WechatNews.ChangesetView, "error.json", changeset: changeset)
    end
  end

这很容易,但我也必须在update行动中重复这一点。

1 个答案:

答案 0 :(得分:0)

你可以按照

的方式做点什么
def changeset(struct, params) do
  struct
  |> cast([:points], params)
  |> validate_required(:points)
end

def point_changeset(struct, params) do
  struct
  |> changeset(params)
  |> check_points
end

defp check_points(changeset) do
  if get_field(changeset, :points) < 1 do
    add_error(changeset, :points, "too low")
  else
    changeset
  end
end

这将为您提供一个函数point_changeset/2,只有在您需要检查用户是否可以根据其点执行某项操作时,才能使用该函数。它仍然会调用具有您希望始终运行的验证的主changeset/2函数。