【问题标题】:Shall I use changeset when update existing data in Ecto?更新 Ecto 中的现有数据时,我应该使用变更集吗?
【发布时间】:2019-08-28 12:22:49
【问题描述】:

我在变更集管道中有加密令牌的功能。

def changeset(user, params \\ %{}) do
  user
  |> cast(params, [:id, :token]
  |> encrypt(:token)
end

由于这个功能是新的,所以旧的数据仍然没有加密,我需要手动做。然后我遇到了问题。

如果我将原始的 token 传递给变更集,它会将值视为没有更改。管道中的encrypt 不起作用,值未更新。

如果我加密了 token 并传递给变更集,它将标记为更改,并应用了 encrypt 函数。但是,它加密了twice

一种笨拙的方法是在encrypt 上添加检查以检查token 是否已加密。但请记住,在我们将新令牌传递给变更集之前,我们仍然需要检查令牌是否已加密。也就是说,我们会进行两次检查。

所以如果有人有这个想法,我正在寻找一个简单的解决方案。

干杯

【问题讨论】:

    标签: elixir phoenix-framework ecto


    【解决方案1】:

    由于这是一次运行的操作,我会进行迁移,直接调用Ecto.Repo.update/2(不幸的是,我没有找到一种方法在这里调用Ecto.Repo.update_all/3,除非你可以直接在数据库中调用encrypt .)

    defmodule My.Repo.Migrations.EncryptTokens do
      @moduledoc false
      use Ecto.Migration
    
      def up do
        for unencrypted <- from(...) |> Repo.all() do
          unencrypted
          |> Ecto.Changeset.change(token: encrypt(unencrypted.token))
          |> Repo.update()
        end
      end
      def down, do: raise "unrevertable"
    end
    

    旁注:你也可以看看Ecto.Changeset.force_change/3fwiw。

    【讨论】:

    • 你能看看这里吗? stackoverflow.com/questions/57680929/…
    • @JunaidFarooq Lanny Bose 给出的答案有什么问题?这似乎是正确的。
    • 它没有加载 vendor_model: :vendor] 关联。
    • 谢谢@AlekseiMatiushkin,你说得对,我的更新应该采用内部方式,在模型中使用changeforce_change而不是changeset函数(使用cast)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-07
    相关资源
    最近更新 更多