【发布时间】:2016-10-12 09:16:16
【问题描述】:
我在 Phoenix Framework 中有三个模型,User、Post、Vote。 用户只有在获得超过 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_change或add_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 操作中重复它。
【问题讨论】: