2016-07-25 36 views
0

第一:我找到了这个topic,但它不起作用。Elixir Ecto插入空的belongs_to

我有两个型号

Council(1)<->(n)Department 

之间的关系,我想插入理事会未经关系到一个部门。

我有了这个外生模式:

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已被弃用,但凤凰在自身变更与cast/3 & 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 

对于使用默认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> 

回答

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_idnil调用changeset之前,或使用凤凰的scrub_params插件,它做同样的事情对所有空字符串:

# web/controllers/council_controller.ex 
plug :scrub_params, "council" when action in [:create] 

(将"council"更改为字段名称,将[:create]更改为您接受该字段的操作列表。)

+0

wo?t?谢谢。奇迹般有效 :) –