首先:我发现了topic,但它不起作用。
我有两个模型之间的关系
Council(1)<->(n)Department
我想插入一个与部门没有关系的理事会。
我有这个ecto架构:
schema "councils" do
field :name, :string
field :description, :string
belongs_to :department, Db2.Department
many_to_many :students, Db2.Student, join_through: Db2.StudentCouncil
many_to_many :periods, Db2.Period, join_through: Db2.StudentCouncil
timestamps()
end
使用此SQL架构:
CREATE TABLE public.councils
(
id integer NOT NULL DEFAULT nextval('councils_id_seq'::regclass),
name character varying(255),
description character varying(255),
department_id integer,
inserted_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL,
CONSTRAINT councils_pkey PRIMARY KEY (id),
CONSTRAINT councils_department_id_fkey FOREIGN KEY (department_id)
REFERENCES public.departments (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
文档说不推荐使用cast/4
,但是phoenix用cast/3
和&amp;创建了变更集。 validate_required/3
本身。我只添加了department
,以便我有以下变更集:
def changeset(struct, params \\ %{}) do
struct
|> cast(params, [:name, :description, :department_id])
|> validate_required([:name])
|> unique_constraint(:name)
|> assoc_constraint(:department)
end
对于表单I&#39;我正在使用默认的phoenix.html表单元素。 当我提交表格时,凤凰表示如下:
[debug] QUERY OK db=1.2ms queue=0.1ms
SELECT u0."id", u0."uid", u0."is_admin", u0."is_staff", u0."password_hash", u0."inserted_at", u0."updated_at" FROM "users" AS u0 WHERE (u0."id" = $1) [1]
[debug] Processing by Db2.CouncilController.create/2
Parameters: %{"_csrf_token" => "KwpdFCZ/bFN9fwkcXSAYLhRCIzgOAAAAXeoEa4+d1MoT7SvzZpgOdg==", "_utf8" => "✓", "council" => %{"department_id" => "", "description" => "", "name" => "test2"}}
Pipelines: [:browser]
[debug] QUERY OK db=1.2ms queue=0.1ms
#Ecto.Changeset<action: :insert, changes: %{description: "", name: "test2"},
errors: [department_id: {"is invalid", [type: :id]}], data: #Db2.Council<>,
valid?: false>
答案 0 :(得分:1)
问题是您要发送一个空字符串作为department_id
而不是nil
。空字符串不会自动转换为nil
:
iex(1)> MyApp.Post.changeset %MyApp.Post{}, %{"title" => "Hello"}
#Ecto.Changeset<action: nil, changes: %{title: "Hello"}, errors: [],
data: #MyApp.Post<>, valid?: true>
iex(2)> MyApp.Post.changeset %MyApp.Post{}, %{"title" => "Hello", "user_id" => nil}
#Ecto.Changeset<action: nil, changes: %{title: "Hello"}, errors: [],
data: #MyApp.Post<>, valid?: true>
iex(3)> MyApp.Post.changeset %MyApp.Post{}, %{"title" => "Hello", "user_id" => "1"}
#Ecto.Changeset<action: nil, changes: %{title: "Hello", user_id: 1}, errors: [],
data: #MyApp.Post<>, valid?: true>
iex(4)> MyApp.Post.changeset %MyApp.Post{}, %{"title" => "Hello", "user_id" => ""}
#Ecto.Changeset<action: nil, changes: %{title: "Hello"},
errors: [user_id: {"is invalid", [type: :id]}], data: #MyApp.Post<>,
valid?: false>
您可以在调用department_id
之前将nil
显式设置为changeset
,或使用Phoenix的scrub_params
插件,它对所有空字符串执行相同的操作:
# web/controllers/council_controller.ex
plug :scrub_params, "council" when action in [:create]
(将"council"
更改为字段名称,将[:create]
更改为您接受该字段的操作列表。)