【问题标题】:Put constraint on PhoenixFramework changeset对 PhoenixFramework 变更集施加约束
【发布时间】:2016-10-12 09:16:16
【问题描述】:

我在 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 操作中重复它。

【问题讨论】:

    标签: phoenix-framework


    【解决方案1】:

    你可以做一些类似的事情

    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 函数,该函数具有您想要始终运行的验证。

    【讨论】:

    • 我刚刚获取了您拥有的代码并将其放入变更集函数中,以便对其进行验证。我不知道您的应用程序的内部结构。你需要把它放在有意义的地方。
    • points 未在 Vote 架构中定义。 Vote 架构只有 typepost_iduser_id。所以我不能直接从变更集中获得它的价值,我必须用用户获得的所有赞成票和他们所做的反对票来计算它。
    • 这并不是我回答的重点。我向您介绍了如何在变更集中执行此操作,这样您就不需要复制逻辑,但只要您想使用它,您仍然可以进行验证。而不是get_field/2 电话,您将不得不进行计算才能知道有多少点可用...
    猜你喜欢
    • 2022-08-15
    • 2015-11-26
    • 2013-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多