为什么Ecto模型模式中的默认值函数只评估一次以及如何修复?

时间:2016-08-03 21:59:07

标签: elixir ecto

我有这样的架构:

header{
  width:80%;
  overflow: hidden;
  color:#ffffff;
  margin-bottom:1%;
  background: #292E37;
}

header a:link {text-decoration:none;color:#ffffff;}
header a:visited{color:#ffffff;}
header a:hover{color:#292E37;}
header a.active{color:#4db8ff;font-weight:bold;cursor:default}
header h1{text-align: center;}

ul.menu{
  width:40%;
  text-align:center;
  text-decoration:none;
  color: #000000;
  margin-left: auto;
  margin-right: auto;
}

ul.menu li{
  display: inline;
  padding: 1%;
  transition: background 0.2s;
  padding-bottom:2.25%;
}

ul.menu li:hover{
  background:#a7afbe;
  transition: 0.3s ease;
  border-bottom: 3px solid #4db8ff;
}

所有新用户都拥有相同的UUID。模式中的默认值只评估一次?我应该在changeset而不是schema中实现默认值吗?

2 个答案:

答案 0 :(得分:3)

像@Mick一样MacCallum说,:default在编译时在代码中进行评估。如果您正在使用PostgreSQL,则可以通过将数据库中列的默认值更改为gen_random_uuid()来解决此问题。这将使PostgreSQL本身为每条记录生成一个随机UUID值。 gen_random_uuid()需要pgcrypto PostgreSQL扩展名。

生成新的迁移:

$ mix ecto.gen.migration add_default_to_users_activation_key

并用以下内容替换新创建的文件内容:

defmodule MyApp.Repo.Migrations.AddDefaultToUsersActivationKey do
  use Ecto.Migration

  def up do
    execute "CREATE EXTENSION IF NOT EXISTS \"pgcrypto\";"
    alter table(:users) do
      modify :activation_key, :uuid, default: fragment("gen_random_uuid()")
    end
  end

  def down do
    alter table(:users) do
      modify :activation_key, :uuid
    end
  end
end

您还应将read_after_writes: true添加到fieldactivation_key的{​​{1}}声明中,以便在插入后从数据库中读回web/models/user.ex

activation_key

演示:

schema "users" do
  field :activation_key, Ecto.UUID, read_after_writes: true
end

答案 1 :(得分:-1)

您可以将类型更改为Ecto.UUID,并将:autogenerate选项设置为true。不是100%确定这是否有效,但值得一试:)