我们有这么一张表的迁移脚本 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