Eliir Ecto: 复合(多列)唯一约束的Changeset校验
我们有这么一张表的迁移脚本 20160718132517_create_vehicle_change_owner_table.exs 描述了机动车过户的记录
defmodule ElectricProto.Repo.Migrations.CreateVehicleChangeOwnerTable do
use Ecto.Migration
def up do
create table(:vehicle_change_owner) do
add :vehicle_id, :string # 车牌号
add :old_user, :integer # 原车主
add :new_user, :integer # 现车主
add :description, :string # 备注
timestamps
end
这里定义了多列唯一索引
create index(:vehicle_change_owner, [:vehicle_id, :old_user, :new_user], unique: true)
end
def down do
drop table(:vehicle_change_owner)
end
end
这种情况下, 我们需要明确指定索引的名字, 如果你在创建索引的时候没有显示指定名字, 那么默认的名称为:
vehicle_change_owner_vehicle_id_old_user_new_user_index
其命名规则为:
表名称_所有字段名称通过下划线连接_index
在变更集中的数据验证
def changeset(struct, params \ %{}) do
struct
|> cast(params, [
:vehicle_id,
:old_user,
:new_user,
:description
])
|> validate_required([
:vehicle_id,
:old_user,
:new_user,
:description
])
|> unique_constraint(
:username,
name: :vehicle_change_owner_vehicle_id_old_user_new_user_index,
message: "不能插入重复的过户记录"
)
end
vehicle_change_owner_vehicle_id_old_user_new_user_index 这个名字太长, 我们可以在迁移脚本中明确指定名称来缩短一些
create index(
:vehicle_change_owner,
[:vehicle_id, :old_user, :new_user],
name: :vehicle_change_owner_index
)
注意
MySQL 中对值的比较是不区分大小写的, PostgreSQL 默认是区分大小写的, 因此在校验唯一性约束的时候如果需要不区分大小写的比较, 可以用 Ecto.Changeset.update_change/3来明确把的把值转换为小写
cast(data, params, [:email], [])
|> update_change(:email, &String.downcase/1)
|> unique_constraint(:email)
最后展示一个插入数据的例子
def api_post(params) do
changeset = changeset(%MODULE{}, params)
if changeset.valid? do
case Repo.insert(changeset) do
{:ok, struct} ->
Resp.responses.status_201
|> Map.put(:result, %{last_inserted_id: struct.id})
{:error, changeset} ->
errors = Enum.map(changeset.errors, fn error ->
{_key, {msg, _opts}} = error
msg
end)
Resp.responses.status_400
|> Map.put(:error, %{messages: errors})
end
end
end
api_post 函数的 params 参数在Phoenix 框架中被包装成一个Map
关键字:elixir, ecto
版权声明
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处。如若内容有涉嫌抄袭侵权/违法违规/事实不符,请点击 举报 进行投诉反馈!