2016-07-25 16 views
0

Erstens: Ich habe diese topic gefunden, aber es funktioniert nicht.Elixir Ecto Einfügen leer gehört_to

Ich habe eine Beziehung zwischen zwei Modellen

Council(1)<->(n)Department 

und ich möchte, ohne eine Beziehung zu einer Abteilung einen Rat einzufügen.

Ich habe dieses ecto Schema bekam:

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 

mit diesem SQL-Schema:

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 
) 

Die Dokumentation sagt, dass cast/4 ist veraltet, aber Phoenix erstellt die changeset mit cast/3 & validate_required/3 von selbst . Ich habe nur die department, so dass ich die folgende changeset haben:

def changeset(struct, params \\ %{}) do 
    struct 
    |> cast(params, [:name, :description, :department_id]) 
    |> validate_required([:name]) 
    |> unique_constraint(:name) 
    |> assoc_constraint(:department) 
end 

Für die Form Ich bin die die Standard phoenix.html Formularelemente verwenden. Wenn ich das Formular phoenix vorlegen sagt der folgende:

[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> 

Antwort

1

Das Problem ist, dass Sie eine leere Zeichenfolge als department_id statt nil sind zu senden. Leere Zeichenfolgen werden nicht automatisch auf nil Stimmen:

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> 

können Sie entweder explizit gesetzt department_id-nil vor changeset Aufruf oder scrub_params Stecker des verwenden Phoenix, die die gleiche Sache für alle leeren Saiten tut:

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

(Ändern Sie "council" in den Feldnamen und [:create] in die Liste der Aktionen, in denen Sie das Feld akzeptieren.)

+0

woOt? Vielen Dank. Klappt wunderbar :) –